blob: 12b61c7893a0e9b6923b2128b83a47ea0095fffd [file] [log] [blame]
{"config":{"lang":["en"],"min_search_length":3,"prebuild_index":false,"separator":"[\\s\\-]+"},"docs":[{"location":"","text":"","title":"Home"},{"location":"about/","text":"Roadmap Some upcoming features: Full IP support Low power support with ability for drivers to turn on/off low power settings automatically Sensor API, see discussion thread Support for MIPS architecture Support for additional boards The detailed roadmap is tracked on JIRA for Mynewt . Feature Request The WISHLIST at the top of the roadmap on JIRA for Mynewt features all the new ideas awaiting discussion and review. Once the community decides to go ahead with a request, it is scheduled into a release. Generally, effort is made to schedule a requested feature into a particular version no later than 6 weeks prior to the planned release date. If you have suggestions for a new feature, use case, or implementation improvements, file a JIRA ticket with Issue Type set to \"Wish\". Introduce it in the dev@ mailing list with a link to the JIRA ticket. This assumes you have signed up for an account on JIRA and submitted a request to the dev@ mailing list for your JIRA username to be added to the Apache Mynewt (MYNEWT) project. FAQ Questions? Click here","title":"About"},{"location":"about/#roadmap","text":"Some upcoming features: Full IP support Low power support with ability for drivers to turn on/off low power settings automatically Sensor API, see discussion thread Support for MIPS architecture Support for additional boards The detailed roadmap is tracked on JIRA for Mynewt .","title":"Roadmap"},{"location":"about/#feature-request","text":"The WISHLIST at the top of the roadmap on JIRA for Mynewt features all the new ideas awaiting discussion and review. Once the community decides to go ahead with a request, it is scheduled into a release. Generally, effort is made to schedule a requested feature into a particular version no later than 6 weeks prior to the planned release date. If you have suggestions for a new feature, use case, or implementation improvements, file a JIRA ticket with Issue Type set to \"Wish\". Introduce it in the dev@ mailing list with a link to the JIRA ticket. This assumes you have signed up for an account on JIRA and submitted a request to the dev@ mailing list for your JIRA username to be added to the Apache Mynewt (MYNEWT) project.","title":"Feature Request"},{"location":"about/#faq","text":"Questions? Click here","title":"FAQ"},{"location":"community/","text":"Mailing Lists We welcome you to join our mailing lists and get in touch with us! To complete your subscription you have to confirm it by replying to the response sent to you when you email your subscription request!","title":"Community"},{"location":"community/#mailing-lists","text":"We welcome you to join our mailing lists and get in touch with us! To complete your subscription you have to confirm it by replying to the response sent to you when you email your subscription request!","title":"Mailing Lists"},{"location":"documentation/","text":"Documentation Organization The technical literature for Apache Mynewt is organized into three manuals. The first describes the Real Time Operating System (RTOS), its features and capabilities, and how to get it running on your target device. The second one demonstrates how to use the build and packaging tool, Newt , to easily choose firmware modules for your target and compose them into a working executable. The third manual shows how the device management tool, Newtmgr , can communicate with a remote device running Mynewt OS and monitor, configure, and upgrade it. For you to learn and get some hands-on experience, each manual includes one or more tutorials. We encourage that you try them, and do send us your feedback.","title":"Documentation"},{"location":"documentation/#documentation-organization","text":"The technical literature for Apache Mynewt is organized into three manuals. The first describes the Real Time Operating System (RTOS), its features and capabilities, and how to get it running on your target device. The second one demonstrates how to use the build and packaging tool, Newt , to easily choose firmware modules for your target and compose them into a working executable. The third manual shows how the device management tool, Newtmgr , can communicate with a remote device running Mynewt OS and monitor, configure, and upgrade it. For you to learn and get some hands-on experience, each manual includes one or more tutorials. We encourage that you try them, and do send us your feedback.","title":"Documentation Organization"},{"location":"download/","text":"Latest Apache Mynewt OS Release Release Version: Mynewt 0.9.0-incubating Release Date: June 6, 2016 Release Notes Fresh install If you are brand new to Mynewt, go to Quick Start . The Newt tool will automatically download the latest release. If you have already installed the Newt tool but not started any project yet, go to Create Your First Project . The Newt tool will automatically download the latest release. Upgrade If you have already installed the Newt tool and started a project that installed a previous version of Apache Mynewt, upgrade using Newt tool: $ newt upgrade Code in development While the use of one of the official releases listed above is generally recommended, you may be interested in seeing work in progress. The most recent code resides in the develop branch of the Mynewt git repository. You may view or fork the repositories for Mynewt OS and Newt Tool from the Apache mirror on github.com. Apache Mynewt OS mirror on github.com Apache Newt Tool mirror on github.com Alternatively, you can clone the desired branch using git: $ git clone git://github.com/apache/incubator-mynewt-core.git -b develop $ git clone git://github.com/apache/incubator-mynewt-newt.git -b develop A relatively stable version of code in progress can be found in the master branch of the Mynewt git repository. You may access the code for Mynewt OS and Newt Tool from the 'master` branch of the Apache mirror on github.com or clone it using git: $ git clone git://github.com/apache/incubator-mynewt-core.git $ git clone git://github.com/apache/incubator-mynewt-newt.git For general information on using Git at Apache, go to https://git-wip-us.apache.org. Release Archives Mynewt 0.8.0-incubating, Release Notes Mynewt 0.8.0-b2-incubating, Release Notes","title":"Download"},{"location":"download/#latest-apache-mynewt-os-release","text":"Release Version: Mynewt 0.9.0-incubating Release Date: June 6, 2016 Release Notes","title":"Latest Apache Mynewt OS Release"},{"location":"download/#fresh-install","text":"If you are brand new to Mynewt, go to Quick Start . The Newt tool will automatically download the latest release. If you have already installed the Newt tool but not started any project yet, go to Create Your First Project . The Newt tool will automatically download the latest release.","title":"Fresh install"},{"location":"download/#upgrade","text":"If you have already installed the Newt tool and started a project that installed a previous version of Apache Mynewt, upgrade using Newt tool: $ newt upgrade","title":"Upgrade"},{"location":"download/#code-in-development","text":"While the use of one of the official releases listed above is generally recommended, you may be interested in seeing work in progress. The most recent code resides in the develop branch of the Mynewt git repository. You may view or fork the repositories for Mynewt OS and Newt Tool from the Apache mirror on github.com. Apache Mynewt OS mirror on github.com Apache Newt Tool mirror on github.com Alternatively, you can clone the desired branch using git: $ git clone git://github.com/apache/incubator-mynewt-core.git -b develop $ git clone git://github.com/apache/incubator-mynewt-newt.git -b develop A relatively stable version of code in progress can be found in the master branch of the Mynewt git repository. You may access the code for Mynewt OS and Newt Tool from the 'master` branch of the Apache mirror on github.com or clone it using git: $ git clone git://github.com/apache/incubator-mynewt-core.git $ git clone git://github.com/apache/incubator-mynewt-newt.git For general information on using Git at Apache, go to https://git-wip-us.apache.org.","title":"Code in development"},{"location":"download/#release-archives","text":"Mynewt 0.8.0-incubating, Release Notes Mynewt 0.8.0-b2-incubating, Release Notes","title":"Release Archives"},{"location":"events/","text":"Events Please take a look at our upcoming events! We hope to see you there.","title":"Events"},{"location":"events/#events","text":"Please take a look at our upcoming events! We hope to see you there.","title":"Events"},{"location":"known_issues/","text":"Known Issues Here is a list of known issues and workarounds: newt install returns the following error: ReadDesc: No matching branch for apache-mynewt-core repo No matching branch for apache-mynewt-core repo The apache-mynewt-core Git repository location has changed due to Mynewt's graduation from an incubator project to an Apache top level project. The HTTP redirect to the new location may fail for some users. Workaround: Edit the project.yml file and change the line repo: incubator-mynewt-core as shown in the following example to repo: mynewt-core : repository.apache-mynewt-core: type: github vers: 1-latest user: apache repo: incubator-mynewt-core","title":"Known Issues"},{"location":"known_issues/#known-issues","text":"Here is a list of known issues and workarounds: newt install returns the following error: ReadDesc: No matching branch for apache-mynewt-core repo No matching branch for apache-mynewt-core repo The apache-mynewt-core Git repository location has changed due to Mynewt's graduation from an incubator project to an Apache top level project. The HTTP redirect to the new location may fail for some users. Workaround: Edit the project.yml file and change the line repo: incubator-mynewt-core as shown in the following example to repo: mynewt-core : repository.apache-mynewt-core: type: github vers: 1-latest user: apache repo: incubator-mynewt-core","title":"Known Issues"},{"location":"quick-start/","text":"Get set Apache Mynewt currently offers two ways to quickly get set up, each appealing to different personal preferences and levels of familiarity with embedded systems. Option 1: All-in-one docker container that bundles Newt tool, developer toolchains and libraries. For this option, go to Docker instructions Option 2: Step-by-step instructions to install the Newt tool, developer toolchains and libraries natively on your computer. For this option, go to Native Setup Go! Start a new project as explained under Create Your First Project . The core Mynewt OS is automatically downloaded as part of the project installation. When you Create Your First Project you define a simulated target and run Project Blinky, the Hello World equivalent in the embedded world. If you have one of the supported boards , you can make real LEDs blink in Project Blinky . Simply choose the appropriate tutorial for the board and proceed. And More... Explore the Tutorials section for other interesting projects or simply to learn more about Mynewt's capabilities and get familiar with its use.","title":"Quick Start"},{"location":"quick-start/#get-set","text":"Apache Mynewt currently offers two ways to quickly get set up, each appealing to different personal preferences and levels of familiarity with embedded systems. Option 1: All-in-one docker container that bundles Newt tool, developer toolchains and libraries. For this option, go to Docker instructions Option 2: Step-by-step instructions to install the Newt tool, developer toolchains and libraries natively on your computer. For this option, go to Native Setup","title":"Get set"},{"location":"quick-start/#go","text":"Start a new project as explained under Create Your First Project . The core Mynewt OS is automatically downloaded as part of the project installation. When you Create Your First Project you define a simulated target and run Project Blinky, the Hello World equivalent in the embedded world. If you have one of the supported boards , you can make real LEDs blink in Project Blinky . Simply choose the appropriate tutorial for the board and proceed.","title":"Go!"},{"location":"quick-start/#and-more","text":"Explore the Tutorials section for other interesting projects or simply to learn more about Mynewt's capabilities and get familiar with its use.","title":"And More..."},{"location":"talks/","text":"","title":"Talks"},{"location":"faq/answers/","text":"How do I submit a bug? If you do not have a JIRA account sign up for an account on JIRA . Submit a request to the @dev mailing list for your JIRA username to be added to the Apache Mynewt (MYNEWT) project. You can view the issues on JIRA for the MYNEWT project without an account but you need to log in for reporting a bug. Log in. Choose the \"MYNEWT\" project. Click on the \"Create\" button to create a ticket. Choose \"Bug\" as the Issue Type. Fill in the bug description, how it is triggered, and other details. How do I request a feature? If you do not have a JIRA account sign up for an account on JIRA . Submit a request to the @dev mailing list for your JIRA username to be added to the Apache Mynewt (MYNEWT) project. You can view the issues on JIRA for the MYNEWT project without an account but you need to log in for reporting a bug. Log in. Choose the \"MYNEWT\" project. Click on the \"Create\" button to create a ticket. Choose \"Wish\" as the Issue Type. Fill in the feature description, benefits, and any other implementation details. Note in the description whether you want to work on it yourself. If you are not a committer and you wish to work on it, someone who is on the committer list will have to review your request and assign it to you. You will have to refer to this JIRA ticket in your pull request. I am not on the committer list. How do I submit a patch? You submit your proposed changes for your peers with committer status to review and merge. The process to submit a Pull Request on github.com is described on the Confluence page for the project . I am a committer in the project. Can I merge my own Pull Request into the git repository? Yes, but only if your Pull Request has been reviewed and approved by another committer in Apache Mynewt. The process to merge a Pull Request is described on the Confluence page for the project . I would like to make some edits to the documentation. What do I do? You submit your proposed changes for your peers with committer status to review and merge. Go to the documentation mirror on github.com. Navigate to the file you wish to edit on github.com. All the technical documentation is in Markdown files under the /docs directory. Click on the pencil icon (\"Edit the file in your fork of this project\") and start making changes. Click the green \"Propose file change\" button. You will be directed to the page where you can start a pull request from the branch that was created for you. The branch is gets an automatic name patch-# where # is a number. Click on the green \"Compare & pull request\" to open the pull request. In the comment for the pull request, include a description of the changes you have made and why. Github will automatically notify everyone on the commits@mynewt.incubator.apache.org mailing list about the newly opened pull requests. You can open a pull request even if you don't think the code is ready for merging but want some discussion on the matter. Upon receiving notification, one or more committers will review your work, ask for edits or clarifications, and merge when your proposed changes are ready. If you want to withdraw the pull request simply go to your fork https://github.com/<your github username>/incubator-mynewt-site and click on \"branches\". You should see your branch under \"Your branches\". Click on the delete icon. I would like to make some edits to the documentation but want to use an editor on my own laptop. What do I do? You submit your proposed changes for your peers with committer status to review and merge. Go to the documentation mirror on github.com. You need to create your own fork of the repo in github.com by clicking on the \"Fork\" button on the top right. Clone the forked repository into your laptop (using git clone from a terminal or using the download buttons on the github page)and create a local branch for the edits and switching to it (using git checkout -b <new-branchname> or GitHub Desktop). Make your changes using the editor of your choice. Push that branch to your fork on github. Then submit a pull request from that branch on your github fork. The review and merge process is the same as other pull requests described for earlier questions.","title":"FAQ"},{"location":"faq/answers/#how-do-i-submit-a-bug","text":"If you do not have a JIRA account sign up for an account on JIRA . Submit a request to the @dev mailing list for your JIRA username to be added to the Apache Mynewt (MYNEWT) project. You can view the issues on JIRA for the MYNEWT project without an account but you need to log in for reporting a bug. Log in. Choose the \"MYNEWT\" project. Click on the \"Create\" button to create a ticket. Choose \"Bug\" as the Issue Type. Fill in the bug description, how it is triggered, and other details.","title":"How do I submit a bug?"},{"location":"faq/answers/#how-do-i-request-a-feature","text":"If you do not have a JIRA account sign up for an account on JIRA . Submit a request to the @dev mailing list for your JIRA username to be added to the Apache Mynewt (MYNEWT) project. You can view the issues on JIRA for the MYNEWT project without an account but you need to log in for reporting a bug. Log in. Choose the \"MYNEWT\" project. Click on the \"Create\" button to create a ticket. Choose \"Wish\" as the Issue Type. Fill in the feature description, benefits, and any other implementation details. Note in the description whether you want to work on it yourself. If you are not a committer and you wish to work on it, someone who is on the committer list will have to review your request and assign it to you. You will have to refer to this JIRA ticket in your pull request.","title":"How do I request a feature?"},{"location":"faq/answers/#i-am-not-on-the-committer-list-how-do-i-submit-a-patch","text":"You submit your proposed changes for your peers with committer status to review and merge. The process to submit a Pull Request on github.com is described on the Confluence page for the project .","title":"I am not on the committer list. How do I submit a patch?"},{"location":"faq/answers/#i-am-a-committer-in-the-project-can-i-merge-my-own-pull-request-into-the-git-repository","text":"Yes, but only if your Pull Request has been reviewed and approved by another committer in Apache Mynewt. The process to merge a Pull Request is described on the Confluence page for the project .","title":"I am a committer in the project. Can I merge my own Pull Request into the git repository?"},{"location":"faq/answers/#i-would-like-to-make-some-edits-to-the-documentation-what-do-i-do","text":"You submit your proposed changes for your peers with committer status to review and merge. Go to the documentation mirror on github.com. Navigate to the file you wish to edit on github.com. All the technical documentation is in Markdown files under the /docs directory. Click on the pencil icon (\"Edit the file in your fork of this project\") and start making changes. Click the green \"Propose file change\" button. You will be directed to the page where you can start a pull request from the branch that was created for you. The branch is gets an automatic name patch-# where # is a number. Click on the green \"Compare & pull request\" to open the pull request. In the comment for the pull request, include a description of the changes you have made and why. Github will automatically notify everyone on the commits@mynewt.incubator.apache.org mailing list about the newly opened pull requests. You can open a pull request even if you don't think the code is ready for merging but want some discussion on the matter. Upon receiving notification, one or more committers will review your work, ask for edits or clarifications, and merge when your proposed changes are ready. If you want to withdraw the pull request simply go to your fork https://github.com/<your github username>/incubator-mynewt-site and click on \"branches\". You should see your branch under \"Your branches\". Click on the delete icon.","title":"I would like to make some edits to the documentation. What do I do?"},{"location":"faq/answers/#i-would-like-to-make-some-edits-to-the-documentation-but-want-to-use-an-editor-on-my-own-laptop-what-do-i-do","text":"You submit your proposed changes for your peers with committer status to review and merge. Go to the documentation mirror on github.com. You need to create your own fork of the repo in github.com by clicking on the \"Fork\" button on the top right. Clone the forked repository into your laptop (using git clone from a terminal or using the download buttons on the github page)and create a local branch for the edits and switching to it (using git checkout -b <new-branchname> or GitHub Desktop). Make your changes using the editor of your choice. Push that branch to your fork on github. Then submit a pull request from that branch on your github fork. The review and merge process is the same as other pull requests described for earlier questions.","title":"I would like to make some edits to the documentation but want to use an editor on my own laptop. What do I do?"},{"location":"faq/go_env/","text":"Contributing to Newt or Newtmgr Tools Newt and Newtmgr are written in Go (golang). This guide shows you how to install Go and setup your environment to update and build the tools if you want to: Contribute to newt or newtmgr features or fix bugs. Build the tools with latest updates from the master branch on a Linux platform. This guide shows you how to perform the following: Install Go on either Mac OS X or Linux. (Tasks that are specific to each platform are called out.) Setup the Go environment. Download the source, build, and install the newt or newtmgr tools. Update and rebuild the tools. Note: You will also need to read and follow the instructions from the FAQ to set up your git repos to submit changes. Step 1: Installing Go The latest master branch of newt and newtmgr requires GO version 1.6 or higher. You can skip this step and proceed to Step 2 if you already have Go version 1.6 or higher installed. Installing Go on Mac OS X If you do not have Homebrew installed, run the following command. You will be prompted for your sudo password. $ ruby -e \"$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)\" You can also extract (or git clone ) Homebrew and install it to /usr/local. Use brew to install Go: $ brew install go ==> ... ... ==> *Summary* \ud83c\udf7a //usr/local/Cellar/go/1.8.1: 7,030 files, 281.8MB, built in 1 minute 12 seconds You can also download the Go package directly from (https://golang.org/dl/) instead of brewing it. Install it in /usr/local directory. Installing Go on Linux Use apt-get to install Go: $sudo apt-get update $sudo apt-get install golang Reading package lists... Done Building dependency tree Reading state information... Done ... The following NEW packages will be installed: golang 0 upgraded, 1 newly installed, 0 to remove and 43 not upgraded. Need to get 0 B/2,812 B of archives. After this operation, 10.2 kB of additional disk space will be used. Selecting previously unselected package golang. (Reading database ... 244990 files and directories currently installed.) Preparing to unpack .../golang_2%3a1.6.1+1ubuntu2_all.deb ... Unpacking golang (2:1.6.1+1ubuntu2) ... Setting up golang (2:1.6.1+1ubuntu2) ... $ go version go version go1.6.3 linux/amd64 Step 2: Setting Up Your Go Environment This section describes the Go environment and how to setup a Go workspace. If you already have a Go workspace for your other Go projects, you can skip this step and proceed to Step 3. Go provides an environment to compile Go code, construct Go packages, and import Go code. You will use Go commands to import the newt or newtmgr package repository into your local Go environment. The Go language environment dictates a specific directory structure, or workspace in Go parlance. It must contain three sibling directories with the names src , pkg and bin : src contains Go source files organized into packages (one package per directory) pkg contains package objects bin contains the Go application executables that Go builds and installs. The GOPATH environment variable specifies the location of your workspace. To setup this workspace environment, create a dev directory and then a go directory under it. Set the GOPATH environment variable to this directory where you will clone the newt and newtmgr repositories. $ cd $HOME $ mkdir -p dev/go $ cd dev/go $ export GOPATH=`pwd` Add the following export statements to your ~/.bash_profile file and source the file: export GOPATH=$HOME/dev/go export PATH=$GOPATH/bin:$PATH Step 3: Downloading the Source and Installing the Tools Newt and newtmgr are individual Go packages and have their own git repositories. You can download the source and install one or both tools. We use the go get command to download the source, build, and install the binary in the $GOPATH/bin directory. Downloading and Installing the Newt Tool The newt Go package is mynewt.apache.org/newt/newt and is stored in the Apache Mynewt newt tool repository mirrored on github . Download the newt package source and install the tool: $cd $GOPATH $go get mynewt.apache.org/newt/newt $cd $GOPATH/src/mynewt.apache.org/newt $ls DISCLAIMER RELEASE_NOTES.md util INSTALLING.md build.sh viper LICENSE newt yaml NOTICE newtmgr README.md newtvm $git status On branch master Your branch is up-to-date with 'origin/master'. nothing to commit, working directory clean Note: The source code under the newtmgr directory is no longer used or updated. The current newtmgr source has its own Git repository. Check that the newt binary is installed and you are using the one from ** $GOPATH/bin**: $ls $GOPATH/bin/newt ~/dev/go/bin/newt $which newt ~/dev/go/bin/newt $newt version Apache Newt (incubating) version: 1.0.0-dev Downloading and Installing the Newtmgr Tool The newtmgr Go package is mynewt.apache.org/newtmgr/newtmgr . It is stored in the Apache Mynewt newtmgr tool repository mirrored on github . Download the newtmgr package and install the tool: Note: -ldflags -s must be passed to the go get command. $cd $GOPATH $go get -ldflags -s mynewt.apache.org/newtmgr/newtmgr $cd $GOPATH/src/mynewt.apache.org/newtmgr $ls DISCLAIMER NOTICE newtmgr LICENSE README.md nmxact $git status On branch master Your branch is up-to-date with 'origin/master'. nothing to commit, working directory clean Check that the newtmgr binary is installed and you are using the one from $GOPATH/bin : $ls $GOPATH/bin/newtmgr ~/dev/go/bin/newtmgr $which newtmgr ~/dev/go/bin/newtmgr Step 4: Updating and Rebuilding the Tools: This section shows you how to rebuild the newt and newtmgr tools with the latest updates from the master branch or after you have made changes in your branch. Here is the general procedure to rebuild either the newt or newtmgr tool. The only difference is the directory where you will be executing the commands from. You will need to repeat the procedure to rebuild both tools. Change to the directory where the local Git repository for the tool is installed. Pull the latest changes from the master branch. If you made changes you will need to rebase with origin master (See FAQ ). Build and install the tool. Change to the directory where the source for the tool is installed. For the newt tool: $cd $GOPATH/src/mynewt.apache.org/newt/newt For the newtmgr tool: $cd $GOPATH/src/mynewt.apache.org/newtmgr/newtmgr After you change to the specific tool directory, get the latest updates from the master branch. If you made changes and need to rebase with the origin, add the --rebase origin master arguments to the git pull command: $git pull Build and install the tool. The updated binary will be installed in the $GOPATH/bin directory: ( Note: -ldflags -s must be passed to the go install command if you are rebuilding newtmgr) $go install You can run the ls -l command to check the modification time for the binary to ensure the new version is installed.","title":"Setting Up Go to Contribute to Newt and Newtmgr Tools"},{"location":"faq/go_env/#contributing-to-newt-or-newtmgr-tools","text":"Newt and Newtmgr are written in Go (golang). This guide shows you how to install Go and setup your environment to update and build the tools if you want to: Contribute to newt or newtmgr features or fix bugs. Build the tools with latest updates from the master branch on a Linux platform. This guide shows you how to perform the following: Install Go on either Mac OS X or Linux. (Tasks that are specific to each platform are called out.) Setup the Go environment. Download the source, build, and install the newt or newtmgr tools. Update and rebuild the tools. Note: You will also need to read and follow the instructions from the FAQ to set up your git repos to submit changes.","title":"Contributing to Newt or Newtmgr Tools"},{"location":"faq/go_env/#step-1-installing-go","text":"The latest master branch of newt and newtmgr requires GO version 1.6 or higher. You can skip this step and proceed to Step 2 if you already have Go version 1.6 or higher installed.","title":"Step 1: Installing Go"},{"location":"faq/go_env/#installing-go-on-mac-os-x","text":"If you do not have Homebrew installed, run the following command. You will be prompted for your sudo password. $ ruby -e \"$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)\" You can also extract (or git clone ) Homebrew and install it to /usr/local. Use brew to install Go: $ brew install go ==> ... ... ==> *Summary* \ud83c\udf7a //usr/local/Cellar/go/1.8.1: 7,030 files, 281.8MB, built in 1 minute 12 seconds You can also download the Go package directly from (https://golang.org/dl/) instead of brewing it. Install it in /usr/local directory.","title":"Installing Go on Mac OS X"},{"location":"faq/go_env/#installing-go-on-linux","text":"Use apt-get to install Go: $sudo apt-get update $sudo apt-get install golang Reading package lists... Done Building dependency tree Reading state information... Done ... The following NEW packages will be installed: golang 0 upgraded, 1 newly installed, 0 to remove and 43 not upgraded. Need to get 0 B/2,812 B of archives. After this operation, 10.2 kB of additional disk space will be used. Selecting previously unselected package golang. (Reading database ... 244990 files and directories currently installed.) Preparing to unpack .../golang_2%3a1.6.1+1ubuntu2_all.deb ... Unpacking golang (2:1.6.1+1ubuntu2) ... Setting up golang (2:1.6.1+1ubuntu2) ... $ go version go version go1.6.3 linux/amd64","title":"Installing Go on Linux"},{"location":"faq/go_env/#step-2-setting-up-your-go-environment","text":"This section describes the Go environment and how to setup a Go workspace. If you already have a Go workspace for your other Go projects, you can skip this step and proceed to Step 3. Go provides an environment to compile Go code, construct Go packages, and import Go code. You will use Go commands to import the newt or newtmgr package repository into your local Go environment. The Go language environment dictates a specific directory structure, or workspace in Go parlance. It must contain three sibling directories with the names src , pkg and bin : src contains Go source files organized into packages (one package per directory) pkg contains package objects bin contains the Go application executables that Go builds and installs. The GOPATH environment variable specifies the location of your workspace. To setup this workspace environment, create a dev directory and then a go directory under it. Set the GOPATH environment variable to this directory where you will clone the newt and newtmgr repositories. $ cd $HOME $ mkdir -p dev/go $ cd dev/go $ export GOPATH=`pwd` Add the following export statements to your ~/.bash_profile file and source the file: export GOPATH=$HOME/dev/go export PATH=$GOPATH/bin:$PATH","title":"Step 2: Setting Up Your Go Environment"},{"location":"faq/go_env/#step-3-downloading-the-source-and-installing-the-tools","text":"Newt and newtmgr are individual Go packages and have their own git repositories. You can download the source and install one or both tools. We use the go get command to download the source, build, and install the binary in the $GOPATH/bin directory.","title":"Step 3: Downloading the Source and Installing the Tools"},{"location":"faq/go_env/#downloading-and-installing-the-newt-tool","text":"The newt Go package is mynewt.apache.org/newt/newt and is stored in the Apache Mynewt newt tool repository mirrored on github . Download the newt package source and install the tool: $cd $GOPATH $go get mynewt.apache.org/newt/newt $cd $GOPATH/src/mynewt.apache.org/newt $ls DISCLAIMER RELEASE_NOTES.md util INSTALLING.md build.sh viper LICENSE newt yaml NOTICE newtmgr README.md newtvm $git status On branch master Your branch is up-to-date with 'origin/master'. nothing to commit, working directory clean Note: The source code under the newtmgr directory is no longer used or updated. The current newtmgr source has its own Git repository. Check that the newt binary is installed and you are using the one from ** $GOPATH/bin**: $ls $GOPATH/bin/newt ~/dev/go/bin/newt $which newt ~/dev/go/bin/newt $newt version Apache Newt (incubating) version: 1.0.0-dev","title":"Downloading and Installing the Newt Tool"},{"location":"faq/go_env/#downloading-and-installing-the-newtmgr-tool","text":"The newtmgr Go package is mynewt.apache.org/newtmgr/newtmgr . It is stored in the Apache Mynewt newtmgr tool repository mirrored on github . Download the newtmgr package and install the tool: Note: -ldflags -s must be passed to the go get command. $cd $GOPATH $go get -ldflags -s mynewt.apache.org/newtmgr/newtmgr $cd $GOPATH/src/mynewt.apache.org/newtmgr $ls DISCLAIMER NOTICE newtmgr LICENSE README.md nmxact $git status On branch master Your branch is up-to-date with 'origin/master'. nothing to commit, working directory clean Check that the newtmgr binary is installed and you are using the one from $GOPATH/bin : $ls $GOPATH/bin/newtmgr ~/dev/go/bin/newtmgr $which newtmgr ~/dev/go/bin/newtmgr","title":"Downloading and Installing the Newtmgr Tool"},{"location":"faq/go_env/#step-4-updating-and-rebuilding-the-tools","text":"This section shows you how to rebuild the newt and newtmgr tools with the latest updates from the master branch or after you have made changes in your branch. Here is the general procedure to rebuild either the newt or newtmgr tool. The only difference is the directory where you will be executing the commands from. You will need to repeat the procedure to rebuild both tools. Change to the directory where the local Git repository for the tool is installed. Pull the latest changes from the master branch. If you made changes you will need to rebase with origin master (See FAQ ). Build and install the tool. Change to the directory where the source for the tool is installed. For the newt tool: $cd $GOPATH/src/mynewt.apache.org/newt/newt For the newtmgr tool: $cd $GOPATH/src/mynewt.apache.org/newtmgr/newtmgr After you change to the specific tool directory, get the latest updates from the master branch. If you made changes and need to rebase with the origin, add the --rebase origin master arguments to the git pull command: $git pull Build and install the tool. The updated binary will be installed in the $GOPATH/bin directory: ( Note: -ldflags -s must be passed to the go install command if you are rebuilding newtmgr) $go install You can run the ls -l command to check the modification time for the binary to ensure the new version is installed.","title":"Step 4: Updating and Rebuilding the Tools:"},{"location":"faq/how_to_edit_docs/","text":"How to Edit Docs Objective Learn the process of editing docs by adding some content to a test document. Markdown, MkDocs, Mou The Mynewt documentation you see on the Apache incubator website is a bunch of HTML files generated using MkDocs which is a simple static site generation tool geared towards building project documentation. You can read about it at http://www.mkdocs.org . Documentation source files are written in Markdown, and configured with a single YAML configuration file. Markdown is a lightweight markup language with plain text formatting syntax designed so that it can be converted to HTML and many other formats using a tool (which in our case is MkDocs). The HTML pages are generated periodically after changes have been reviewed and accepted into the master branch. Access to the Apache repo Get an account on Apache. You do not need a committer account to view the website or clone the repository but you need it to push changes to it. If you are not a committer, you may follow the proposed non-committer workflow to share your work. The direct link to the proposed workflow is https://git-wip-us.apache.org/docs/workflow.html . You will find the steps described in more detail later in this tutorial. Editing an existing page Create a fork on the github mirror . Create a new branch to work on your documentation and move to that branch. $ git checkout -b <your-branch-name> Make changes directly on github.com. Generate a pull request. Alternatively, you can edit locally on your machine, push the branch (or the changes in the branch) to your fork on github.com, and then generate a pull request. Adding a new page If you create a new file somewhere in the docs subdirectory to add a new page, you have to add a line in the mkdocs.yml file at the correct level. For example, if you add a new module named \"Wi-Fi\" by creating a new file named wifi.md in the network directory, you have to insert the following line under Networking User Guide in the mkdocs.yml file (at the same level as the docs directory). In this example, a link will show up in the navigation bar on the left under \"Networking User Guide\" titled \"Wi-Fi\" and take the user to the contents of the 'wifi.md' file when the link is clicked. ** Note: The change will show up on this Mynewt site only after your pull request is merged in and the updated site is generated.** - 'Wi-Fi': 'wifi.md' Local preview of HTML files You have the option to install MkDocs and do a local conversion yourself to preview the pages using the built-in webserver that comes with MkDocs. In order to install MkDocs you'll need Python installed on your system, as well as the Python package manager, pip. You can check if you have them already (usually you will). $ python --version Python 2.7.2 $ pip --version pip 1.5.2 $ pip install mkdocs You will then run the built-in webserver from the root of the documentation directory using the command mkdocs serve . The root directory for documentation is incubator-mynewt-site or the directory with the mkdocs.yml file. $ ls docs images mkdocs.yml $ mkdocs serve Then go to http://127.0.0.1:8000 to preview your pages and see how they will look on the website. Remember that the MyNewt website itself will not be updated. For more information on MkDocs go to http://www.mkdocs.org .","title":"Edit Docs"},{"location":"faq/how_to_edit_docs/#how-to-edit-docs","text":"","title":"How to Edit Docs"},{"location":"faq/how_to_edit_docs/#objective","text":"Learn the process of editing docs by adding some content to a test document.","title":"Objective"},{"location":"faq/how_to_edit_docs/#markdown-mkdocs-mou","text":"The Mynewt documentation you see on the Apache incubator website is a bunch of HTML files generated using MkDocs which is a simple static site generation tool geared towards building project documentation. You can read about it at http://www.mkdocs.org . Documentation source files are written in Markdown, and configured with a single YAML configuration file. Markdown is a lightweight markup language with plain text formatting syntax designed so that it can be converted to HTML and many other formats using a tool (which in our case is MkDocs). The HTML pages are generated periodically after changes have been reviewed and accepted into the master branch.","title":"Markdown, MkDocs, Mou"},{"location":"faq/how_to_edit_docs/#access-to-the-apache-repo","text":"Get an account on Apache. You do not need a committer account to view the website or clone the repository but you need it to push changes to it. If you are not a committer, you may follow the proposed non-committer workflow to share your work. The direct link to the proposed workflow is https://git-wip-us.apache.org/docs/workflow.html . You will find the steps described in more detail later in this tutorial.","title":"Access to the Apache repo"},{"location":"faq/how_to_edit_docs/#editing-an-existing-page","text":"Create a fork on the github mirror . Create a new branch to work on your documentation and move to that branch. $ git checkout -b <your-branch-name> Make changes directly on github.com. Generate a pull request. Alternatively, you can edit locally on your machine, push the branch (or the changes in the branch) to your fork on github.com, and then generate a pull request.","title":"Editing an existing page"},{"location":"faq/how_to_edit_docs/#adding-a-new-page","text":"If you create a new file somewhere in the docs subdirectory to add a new page, you have to add a line in the mkdocs.yml file at the correct level. For example, if you add a new module named \"Wi-Fi\" by creating a new file named wifi.md in the network directory, you have to insert the following line under Networking User Guide in the mkdocs.yml file (at the same level as the docs directory). In this example, a link will show up in the navigation bar on the left under \"Networking User Guide\" titled \"Wi-Fi\" and take the user to the contents of the 'wifi.md' file when the link is clicked. ** Note: The change will show up on this Mynewt site only after your pull request is merged in and the updated site is generated.** - 'Wi-Fi': 'wifi.md'","title":"Adding a new page"},{"location":"faq/how_to_edit_docs/#local-preview-of-html-files","text":"You have the option to install MkDocs and do a local conversion yourself to preview the pages using the built-in webserver that comes with MkDocs. In order to install MkDocs you'll need Python installed on your system, as well as the Python package manager, pip. You can check if you have them already (usually you will). $ python --version Python 2.7.2 $ pip --version pip 1.5.2 $ pip install mkdocs You will then run the built-in webserver from the root of the documentation directory using the command mkdocs serve . The root directory for documentation is incubator-mynewt-site or the directory with the mkdocs.yml file. $ ls docs images mkdocs.yml $ mkdocs serve Then go to http://127.0.0.1:8000 to preview your pages and see how they will look on the website. Remember that the MyNewt website itself will not be updated. For more information on MkDocs go to http://www.mkdocs.org .","title":"Local preview of HTML files"},{"location":"faq/ide/","text":"Developing Mynewt Applications with Visual Studio Code This guide shows you how to set up Visual Studio Code to develop and debug Mynewt applications. Visual Studio Code is supported on Mac OS, Linux, and Windows. This guide shows you how to: Install Visual Studio Code. Install the C/C++ and debugger extensions. Define task configurations to build Mynewt applications. Define debugger configurations to debug Mynewt applications. Launch the debugger. Prerequisites: Have Internet connectivity to fetch remote Mynewt components. Have a computer to build a Mynewt application. Perform native installation for the Mynewt tools and toolchains. Note: For Windows platforms, ensure that the MinGW bash you install is added to your Windows Path. In addition, if you are using Windows 10 WSL, you must have the MinGW bash before the Windows 10 WSL bash in your Windows Path. Read the Mynewt OS Concepts section. Create a project space (directory structure) and populate it with the core code repository (apache-mynewt-core) or know how to as explained in Creating Your First Project. Complete one of the Blinky Tutorials . Notes: This guide is not a tutorial for Visual Studio Code. It assumes you are familiar with Visual Studio Code. If this is your first time using Visual Studio Code, we recommend that you read the Visual Studio Code documentation and tutorials and evaluate whether you would like to use it to develop Mynewt applications. This guide uses Visual Studio Code on Windows. Visual Studio Code is supported on Linux and Mac OS but may have some variations in the keyboard shortcuts and command names for these platforms. You can also use the Eclipse IDE to develop Mynewt applications. See https://www.codecoup.pl/blog/hacking-mynewt-in-eclipse for more details. On Windows platforms, you must also ensure the MinGW bash is set in your Windows Path as described in the prerequisites. Installing Visual Studio Code Download and install Visual Studio Code from https://code.visualstudio.com/ . Installing the C/C++ and Debugger Extensions You need to install two extensions: The C/C++ extension from Microsoft. This extension provides language support such as symbol searching, signatuare help, go to definition, and go to declaration. The Native Debug extension from webfreak. This extension provides GDB support. To install the C/C++ extension: Press Ctrl-P to open the search box. Type ext install cpptools in the search box and press Enter. You should see the extension at the top of the list. Click Install to install the extension. To install the Native Debugger: Press Ctrl-P to open the search box. Type ext install webfreak.debug in the search box and press Enter. You should see the Native Debug extension at the top of the list. Click Install to install the extension. Defining Tasks for Mynewt Projects Two main concepts in Visual Studio Code are workspaces and tasks. A workspace represents a folder that is open. You can open multiple workspaces and switch between workspaces. Tasks allow you to integrate the external tools and operations that are used to build or test your project into Visual Studio Code. Tasks are run from and the task results can be analyzed in Visual Studio Code. Tasks are defined within the scope of a workspace. This means that the tasks you define for a workspace only apply to the given workspace. Associating a Mynewt Project to a Workspace For your Mynewt project, your Visual Studio Code workspace is the Mynewt project base directory. For example, if you create a project named myproj under the ~/dev directory, then you open the ~/dev/myproj folder for your workspace. Select File > Open Folder , and select the myproj folder from the Select Folder dialog box to open the folder. Defining Visual Studio Code Tasks to Build and Debug Mynewt Applications You define Visual Studio Code tasks to build and debug your Mynewt targets in Visual Studio Code. We use the Blinky application for the Arduino Zero board from the Blinky On Arduino Zero Tutorial to illustrate how to define the tasks to build and debug the Arduino blinky bootloader and application targets. Perform the following steps to create the tasks to build and debug the Arduino blinky bootloader and appliction targets: Step 1: Press Ctrl-Shift-P , type task , and select Tasks:Configure Task Runner from the search results. Step 2: Select Others (scroll down to the bottom of the list) to create a task runner for external commands. Tasks are defined in the tasks.json file. You should see the .vscode folder created in the MYPROJ folder and a tasks.json file created in the .vscode folder. The tasks.json file has the following default values. The sample tasks.json file defines a simple task that runs the echo command with \"Hello World\" as the argument. Step 3: Delete the content from the tasks.json file, add the following definitions, and press Ctrl-S to save the file. { \"version\": \"0.1.0\", \"command\": \"newt\", \"echoCommand\": true, \"isShellCommand\": true, \"tasks\":[ { \"taskName\": \"build_arduino_boot\", \"args\": [\"build\", \"arduino_boot\"], \"suppressTaskName\": true }, { \"taskName\": \"build_arduino_blinky\", \"args\": [\"build\", \"arduino_blinky\"], \"isBuildCommand\": true, \"suppressTaskName\": true }, { \"taskName\": \"create_arduino_blinky\", \"args\": [\"create-image\", \"arduino_blinky\", \"1.0.0\"], \"suppressTaskName\":true }, { \"taskName\": \"debug_arduino_blinky\", \"args\": [\"debug\", \"arduino_blinky\", \"-n\"], \"suppressTaskName\": true } ] } The tasks.json file specifies the tasks that are run to build and debug the Arduino blinky targets. Each task runs a newt command. The newt command to run and the arguments for the newt command are passed in the args property for each task. The following tasks are defined in this example: build_arduino_boot : Runs the newt build arduino_boot command to build the arduino_boot target. build_arduino_blinky : Runs the newt build arduino_blinky command to build the arduino_blinky target. Note: This task sets the isBuildCommand property to true . This is an optional property that, when set to true, allows you to run the Tasks: Run Build Task ( Ctrl-Shift-B ) command to start the task. create_arduino_blinky : Runs the newt create-image arduino_blinky command to create the image file. debug_arduino_blinky : Runs the newt build arduino_blinky -n command to debug the arduino_blinky target. The -n flag is specified to start only the GDB server and not the GDB client. We will launch the GDB client from Visual Studio Code. For more information on tasks and all supported properties, see the Visual Studio Code Task documentation . Running a Task To run a task, press Ctrl-Shift-P , type task on the search box, and select Tasks: Run Task . The tasks that you define in the tasks.json file are listed. Select the task to run. The following is an example of running the build_arduino_boot task: Note :To run the build_arduino_linky task, you can use the keyboard shortcut Ctrl-Shift-B because the task has the property isBuildCommand set to true. Defining Tasks for Other Newt Commands Other newt commands, such as the newt load command, do not need to run from within Visual Studio Code. You can define a task for each command as a convenience and run the command as a task, or you can run the newt command on the command line from the Visual Studio Code integrated terminal or an external terminal. To create the tasks for the newt load arduino_boot and newt laod arduino_blinky commands, add the following definitions to the tasks.json file: { \"taskName\": \"load_arduino_boot\", \"args\": [\"load\", \"arduino_boot\"], \"suppressTaskName\":true }, { \"taskName\": \"load_arduino_blinky\", \"args\": [\"load\", \"arduino_blinky\"], \"suppressTaskName\":true }, To run a command from the Visual Studio integrated terminal, instead of starting a task, press Ctrl-` to launch the integrated terminal and enter the command on the prompt: Defining Debugger Configurations You need to define a debugger configuration to launch the GDB debugger from within Visual Studio Code: Step 1: Select Debug > Open Configuration , and select the GDB environment. You should see a default launch.json file created in the .vscode folder. Step 2: Delete the content from the launch.json file, add the following definitions, and press 'Ctrl-S' to save the file. { \"version\": \"0.2.0\", \"configurations\": [ { \"name\": \"gdb_arduino_blinky\", \"type\": \"gdb\", \"request\": \"attach\", \"executable\": \"${workspaceRoot}\\\\bin\\\\targets\\\\arduino_blinky\\\\app\\\\apps\\\\blinky\\\\blinky.elf\", \"target\": \":3333\", \"cwd\": \"${workspaceRoot}\", \"gdbpath\": \"C:\\\\Program Files (x86)\\\\GNU Tools ARM Embedded\\\\4.9 2015q2\\\\bin\\\\arm-none-eabi-gdb.exe\", \"remote\": true } ] } This defines a gdb_arduino_blinky debugger configuration. It specifies: The debugger is type gdb . To use the blinky.elf file for the executable. To use port 3333 to connect with the remote target. To use arm-none-eabi-gdb for the GDB program. Debugging Your Application To debug your application, start the GDB server and launch the GDB session from Visual Studio Code. For the the arduino blinky example, perform the following: Step 1: Run the debug_arduino_blinky task to start the GDB server. Perform the following: Press Ctrl-Shift-P and type task in the search box. Select Tasks:Run Task > debug_arduino_blinky . Press Ctrl-Shift-U to open the Output Panel and see the OpenOCD GDB Server output. Step 2: Start the GDB session. Perform the following: Press Ctrl-Shift-Y to view the Debug Console. Press the Debugging icon on the activity bar (Ctrl-Shift-D) to bring up the Debug Side Bar. Select gdb_arduino_blinky from the DEBUG drop down menu. Press the green play button to start the gdb session. Step 3: Debug your application. You should see a debug session similar to the one shown below: For more information on how to use the Visual Studio Code Debugger, see the Visual Studio Code debugging documentation . Working with Multiple Mynewt Applications As mentioned previously, each mynewt project corresponds to a Visual Studio Code workspace. If you have multiple Mynewt application targets defined in same project, you will need to define build and debug tasks for each target in the tasks.json file and debugger configurations for the targets in the launch.json file for the workspace. If you have a different Mynewt project for each mynewt application, you will need to define build and debug tasks in the tasks.json file and the debugger configuration in the launch.json file for each workspace.","title":"Using an IDE to Develop Mynewt Applications"},{"location":"faq/ide/#developing-mynewt-applications-with-visual-studio-code","text":"This guide shows you how to set up Visual Studio Code to develop and debug Mynewt applications. Visual Studio Code is supported on Mac OS, Linux, and Windows. This guide shows you how to: Install Visual Studio Code. Install the C/C++ and debugger extensions. Define task configurations to build Mynewt applications. Define debugger configurations to debug Mynewt applications. Launch the debugger. Prerequisites: Have Internet connectivity to fetch remote Mynewt components. Have a computer to build a Mynewt application. Perform native installation for the Mynewt tools and toolchains. Note: For Windows platforms, ensure that the MinGW bash you install is added to your Windows Path. In addition, if you are using Windows 10 WSL, you must have the MinGW bash before the Windows 10 WSL bash in your Windows Path. Read the Mynewt OS Concepts section. Create a project space (directory structure) and populate it with the core code repository (apache-mynewt-core) or know how to as explained in Creating Your First Project. Complete one of the Blinky Tutorials . Notes: This guide is not a tutorial for Visual Studio Code. It assumes you are familiar with Visual Studio Code. If this is your first time using Visual Studio Code, we recommend that you read the Visual Studio Code documentation and tutorials and evaluate whether you would like to use it to develop Mynewt applications. This guide uses Visual Studio Code on Windows. Visual Studio Code is supported on Linux and Mac OS but may have some variations in the keyboard shortcuts and command names for these platforms. You can also use the Eclipse IDE to develop Mynewt applications. See https://www.codecoup.pl/blog/hacking-mynewt-in-eclipse for more details. On Windows platforms, you must also ensure the MinGW bash is set in your Windows Path as described in the prerequisites.","title":"Developing Mynewt Applications with Visual Studio Code"},{"location":"faq/ide/#installing-visual-studio-code","text":"Download and install Visual Studio Code from https://code.visualstudio.com/ .","title":"Installing Visual Studio Code"},{"location":"faq/ide/#installing-the-cc-and-debugger-extensions","text":"You need to install two extensions: The C/C++ extension from Microsoft. This extension provides language support such as symbol searching, signatuare help, go to definition, and go to declaration. The Native Debug extension from webfreak. This extension provides GDB support. To install the C/C++ extension: Press Ctrl-P to open the search box. Type ext install cpptools in the search box and press Enter. You should see the extension at the top of the list. Click Install to install the extension. To install the Native Debugger: Press Ctrl-P to open the search box. Type ext install webfreak.debug in the search box and press Enter. You should see the Native Debug extension at the top of the list. Click Install to install the extension.","title":"Installing the C/C++ and Debugger Extensions"},{"location":"faq/ide/#defining-tasks-for-mynewt-projects","text":"Two main concepts in Visual Studio Code are workspaces and tasks. A workspace represents a folder that is open. You can open multiple workspaces and switch between workspaces. Tasks allow you to integrate the external tools and operations that are used to build or test your project into Visual Studio Code. Tasks are run from and the task results can be analyzed in Visual Studio Code. Tasks are defined within the scope of a workspace. This means that the tasks you define for a workspace only apply to the given workspace.","title":"Defining Tasks for Mynewt Projects"},{"location":"faq/ide/#associating-a-mynewt-project-to-a-workspace","text":"For your Mynewt project, your Visual Studio Code workspace is the Mynewt project base directory. For example, if you create a project named myproj under the ~/dev directory, then you open the ~/dev/myproj folder for your workspace. Select File > Open Folder , and select the myproj folder from the Select Folder dialog box to open the folder.","title":"Associating a Mynewt Project to a Workspace"},{"location":"faq/ide/#defining-visual-studio-code-tasks-to-build-and-debug-mynewt-applications","text":"You define Visual Studio Code tasks to build and debug your Mynewt targets in Visual Studio Code. We use the Blinky application for the Arduino Zero board from the Blinky On Arduino Zero Tutorial to illustrate how to define the tasks to build and debug the Arduino blinky bootloader and application targets. Perform the following steps to create the tasks to build and debug the Arduino blinky bootloader and appliction targets: Step 1: Press Ctrl-Shift-P , type task , and select Tasks:Configure Task Runner from the search results. Step 2: Select Others (scroll down to the bottom of the list) to create a task runner for external commands. Tasks are defined in the tasks.json file. You should see the .vscode folder created in the MYPROJ folder and a tasks.json file created in the .vscode folder. The tasks.json file has the following default values. The sample tasks.json file defines a simple task that runs the echo command with \"Hello World\" as the argument. Step 3: Delete the content from the tasks.json file, add the following definitions, and press Ctrl-S to save the file. { \"version\": \"0.1.0\", \"command\": \"newt\", \"echoCommand\": true, \"isShellCommand\": true, \"tasks\":[ { \"taskName\": \"build_arduino_boot\", \"args\": [\"build\", \"arduino_boot\"], \"suppressTaskName\": true }, { \"taskName\": \"build_arduino_blinky\", \"args\": [\"build\", \"arduino_blinky\"], \"isBuildCommand\": true, \"suppressTaskName\": true }, { \"taskName\": \"create_arduino_blinky\", \"args\": [\"create-image\", \"arduino_blinky\", \"1.0.0\"], \"suppressTaskName\":true }, { \"taskName\": \"debug_arduino_blinky\", \"args\": [\"debug\", \"arduino_blinky\", \"-n\"], \"suppressTaskName\": true } ] } The tasks.json file specifies the tasks that are run to build and debug the Arduino blinky targets. Each task runs a newt command. The newt command to run and the arguments for the newt command are passed in the args property for each task. The following tasks are defined in this example: build_arduino_boot : Runs the newt build arduino_boot command to build the arduino_boot target. build_arduino_blinky : Runs the newt build arduino_blinky command to build the arduino_blinky target. Note: This task sets the isBuildCommand property to true . This is an optional property that, when set to true, allows you to run the Tasks: Run Build Task ( Ctrl-Shift-B ) command to start the task. create_arduino_blinky : Runs the newt create-image arduino_blinky command to create the image file. debug_arduino_blinky : Runs the newt build arduino_blinky -n command to debug the arduino_blinky target. The -n flag is specified to start only the GDB server and not the GDB client. We will launch the GDB client from Visual Studio Code. For more information on tasks and all supported properties, see the Visual Studio Code Task documentation .","title":"Defining Visual Studio Code Tasks to Build and Debug Mynewt Applications"},{"location":"faq/ide/#running-a-task","text":"To run a task, press Ctrl-Shift-P , type task on the search box, and select Tasks: Run Task . The tasks that you define in the tasks.json file are listed. Select the task to run. The following is an example of running the build_arduino_boot task: Note :To run the build_arduino_linky task, you can use the keyboard shortcut Ctrl-Shift-B because the task has the property isBuildCommand set to true.","title":"Running a Task"},{"location":"faq/ide/#defining-tasks-for-other-newt-commands","text":"Other newt commands, such as the newt load command, do not need to run from within Visual Studio Code. You can define a task for each command as a convenience and run the command as a task, or you can run the newt command on the command line from the Visual Studio Code integrated terminal or an external terminal. To create the tasks for the newt load arduino_boot and newt laod arduino_blinky commands, add the following definitions to the tasks.json file: { \"taskName\": \"load_arduino_boot\", \"args\": [\"load\", \"arduino_boot\"], \"suppressTaskName\":true }, { \"taskName\": \"load_arduino_blinky\", \"args\": [\"load\", \"arduino_blinky\"], \"suppressTaskName\":true }, To run a command from the Visual Studio integrated terminal, instead of starting a task, press Ctrl-` to launch the integrated terminal and enter the command on the prompt:","title":"Defining Tasks for Other Newt Commands"},{"location":"faq/ide/#defining-debugger-configurations","text":"You need to define a debugger configuration to launch the GDB debugger from within Visual Studio Code: Step 1: Select Debug > Open Configuration , and select the GDB environment. You should see a default launch.json file created in the .vscode folder. Step 2: Delete the content from the launch.json file, add the following definitions, and press 'Ctrl-S' to save the file. { \"version\": \"0.2.0\", \"configurations\": [ { \"name\": \"gdb_arduino_blinky\", \"type\": \"gdb\", \"request\": \"attach\", \"executable\": \"${workspaceRoot}\\\\bin\\\\targets\\\\arduino_blinky\\\\app\\\\apps\\\\blinky\\\\blinky.elf\", \"target\": \":3333\", \"cwd\": \"${workspaceRoot}\", \"gdbpath\": \"C:\\\\Program Files (x86)\\\\GNU Tools ARM Embedded\\\\4.9 2015q2\\\\bin\\\\arm-none-eabi-gdb.exe\", \"remote\": true } ] } This defines a gdb_arduino_blinky debugger configuration. It specifies: The debugger is type gdb . To use the blinky.elf file for the executable. To use port 3333 to connect with the remote target. To use arm-none-eabi-gdb for the GDB program.","title":"Defining Debugger Configurations"},{"location":"faq/ide/#debugging-your-application","text":"To debug your application, start the GDB server and launch the GDB session from Visual Studio Code. For the the arduino blinky example, perform the following: Step 1: Run the debug_arduino_blinky task to start the GDB server. Perform the following: Press Ctrl-Shift-P and type task in the search box. Select Tasks:Run Task > debug_arduino_blinky . Press Ctrl-Shift-U to open the Output Panel and see the OpenOCD GDB Server output. Step 2: Start the GDB session. Perform the following: Press Ctrl-Shift-Y to view the Debug Console. Press the Debugging icon on the activity bar (Ctrl-Shift-D) to bring up the Debug Side Bar. Select gdb_arduino_blinky from the DEBUG drop down menu. Press the green play button to start the gdb session. Step 3: Debug your application. You should see a debug session similar to the one shown below: For more information on how to use the Visual Studio Code Debugger, see the Visual Studio Code debugging documentation .","title":"Debugging Your Application"},{"location":"faq/ide/#working-with-multiple-mynewt-applications","text":"As mentioned previously, each mynewt project corresponds to a Visual Studio Code workspace. If you have multiple Mynewt application targets defined in same project, you will need to define build and debug tasks for each target in the tasks.json file and debugger configurations for the targets in the launch.json file for the workspace. If you have a different Mynewt project for each mynewt application, you will need to define build and debug tasks in the tasks.json file and the debugger configuration in the launch.json file for each workspace.","title":"Working with Multiple Mynewt Applications"},{"location":"network/ble/ble_intro/","text":"BLE Introduction Apache Mynewt offers the world's first fully open-source Bluetooth Low Energy (BLE) or Bluetooth Smart stack fully compliant with BLE 4.2 specifications. It is called NimBLE. BLE technology operates in the unlicensed industrial, scientific and medical (ISM) band at 2.4 to 2.485 GHz which is available in most countries. It uses a spread spectrum, frequency hopping, full-duplex signal. BLE FHSS employs 40 2-MHz-wide channels to ensure greater reliability over longer distances. It also features 0-dBm (1 mW) power output and a typical maximum range of 50 meters. Note that BLE is not compatible with standard Bluetooth. Feature Support NimBLE complies with Bluetooth Core Specification 4.2 which introduces several new features that make it an ideal wireless technology for the Internet of Things (IoT). LE Privacy 1.2 for frequent changes to the device address to make it difficult to track for outsiders LE Secure Connections featuring FIPS-compliant algorithms. LE Data Length Extension for higher throughput Coming Soon : Assigning an Internet Protocol (IP) address (complaint with the IPv6 or 6LoWPAN standard) to a Bluetooth device through Internet Protocol Support Profile (IPSP) Components A Bluetooth low energy stack (NimBLE included) consists of two components with several subcomponents: Controller Physical Layer : adaptive frequency-hopping Gaussian Frequency Shift Keying (GFSK) radio using 40 RF channels (0-39), with 2 MHz spacing. Link Layer : with one of five states (Standby, Advertising, Scanning, Initiating, Connection states) active at any time Host Logical Link Control and Adaptation Protocol (L2CAP) : provides logical channels, named L2CAP channels, which are multiplexed over one or more logical links to provide packet segmentation and reassembly, flow control, error control, streaming, QoS etc. Security Manager (SM) : uses Security Manager Protocol (SMP) for pairing and transport specific key distribution for securing radio communication Attribute protocol (ATT) : allows a device ( Server ) to expose certain pieces of data, known as Attributes , to another device ( Client ) Generic Attribute Profile (GATT) : a framework for using the ATT protocol to exchange attributes encapsulated as Characteristics or Services Generic Access Profile (GAP) : a base profile which all Bluetooth devices implement, which in the case of LE, defines the Physical Layer, Link Layer, L2CAP, Security Manager, Attribute Protocol and Generic Attribute Profile. Host Controller Interface (HCI) : the interface between the host and controller either through software API or by a hardware interface such as SPI, UART or USB. Subsequent chapters in this manual will go into the details of the implementation of each component, APIs available, and things to consider while designing a NimBLE app. Example NimBLE projects Mynewt comes with several built-in projects or applications using NimBLE. These allow users to try out NimBLE, understand how to use available services, and build their own applications using one or more of the examples as seed. bletiny : A simple shell application which provides a basic interface to the host-side of the BLE stack. Supported operations include GAP, GATT, and L2CAP. bleprph : A basic peripheral device with no user interface. It advertises automatically on startup, and resumes advertising whenever a connection is terminated. It supports a maximum of one connection. blecent : A basic central device with no user interface. This application scans for a peripheral that supports the alert notification service (ANS). Upon discovering such a peripheral, blecent connects and performs the following actions: Reads the ANS Supported New Alert Category characteristic. Writes the ANS Alert Notification Control Point characteristic. Subscribes to notifications for the ANS Unread Alert Status characteristic. blehci : Implements a BLE controller-only application. A separate host-only implementation, such as Linux's BlueZ, can interface with this application via HCI over UART. bleuart : Implements a simple BLE peripheral that supports the Nordic UART / Serial Port Emulation service","title":"NimBLE Introduction"},{"location":"network/ble/ble_intro/#ble-introduction","text":"Apache Mynewt offers the world's first fully open-source Bluetooth Low Energy (BLE) or Bluetooth Smart stack fully compliant with BLE 4.2 specifications. It is called NimBLE. BLE technology operates in the unlicensed industrial, scientific and medical (ISM) band at 2.4 to 2.485 GHz which is available in most countries. It uses a spread spectrum, frequency hopping, full-duplex signal. BLE FHSS employs 40 2-MHz-wide channels to ensure greater reliability over longer distances. It also features 0-dBm (1 mW) power output and a typical maximum range of 50 meters. Note that BLE is not compatible with standard Bluetooth.","title":"BLE Introduction"},{"location":"network/ble/ble_intro/#feature-support","text":"NimBLE complies with Bluetooth Core Specification 4.2 which introduces several new features that make it an ideal wireless technology for the Internet of Things (IoT). LE Privacy 1.2 for frequent changes to the device address to make it difficult to track for outsiders LE Secure Connections featuring FIPS-compliant algorithms. LE Data Length Extension for higher throughput Coming Soon : Assigning an Internet Protocol (IP) address (complaint with the IPv6 or 6LoWPAN standard) to a Bluetooth device through Internet Protocol Support Profile (IPSP)","title":"Feature Support"},{"location":"network/ble/ble_intro/#components","text":"A Bluetooth low energy stack (NimBLE included) consists of two components with several subcomponents: Controller Physical Layer : adaptive frequency-hopping Gaussian Frequency Shift Keying (GFSK) radio using 40 RF channels (0-39), with 2 MHz spacing. Link Layer : with one of five states (Standby, Advertising, Scanning, Initiating, Connection states) active at any time Host Logical Link Control and Adaptation Protocol (L2CAP) : provides logical channels, named L2CAP channels, which are multiplexed over one or more logical links to provide packet segmentation and reassembly, flow control, error control, streaming, QoS etc. Security Manager (SM) : uses Security Manager Protocol (SMP) for pairing and transport specific key distribution for securing radio communication Attribute protocol (ATT) : allows a device ( Server ) to expose certain pieces of data, known as Attributes , to another device ( Client ) Generic Attribute Profile (GATT) : a framework for using the ATT protocol to exchange attributes encapsulated as Characteristics or Services Generic Access Profile (GAP) : a base profile which all Bluetooth devices implement, which in the case of LE, defines the Physical Layer, Link Layer, L2CAP, Security Manager, Attribute Protocol and Generic Attribute Profile. Host Controller Interface (HCI) : the interface between the host and controller either through software API or by a hardware interface such as SPI, UART or USB. Subsequent chapters in this manual will go into the details of the implementation of each component, APIs available, and things to consider while designing a NimBLE app.","title":"Components"},{"location":"network/ble/ble_intro/#example-nimble-projects","text":"Mynewt comes with several built-in projects or applications using NimBLE. These allow users to try out NimBLE, understand how to use available services, and build their own applications using one or more of the examples as seed. bletiny : A simple shell application which provides a basic interface to the host-side of the BLE stack. Supported operations include GAP, GATT, and L2CAP. bleprph : A basic peripheral device with no user interface. It advertises automatically on startup, and resumes advertising whenever a connection is terminated. It supports a maximum of one connection. blecent : A basic central device with no user interface. This application scans for a peripheral that supports the alert notification service (ANS). Upon discovering such a peripheral, blecent connects and performs the following actions: Reads the ANS Supported New Alert Category characteristic. Writes the ANS Alert Notification Control Point characteristic. Subscribes to notifications for the ANS Unread Alert Status characteristic. blehci : Implements a BLE controller-only application. A separate host-only implementation, such as Linux's BlueZ, can interface with this application via HCI over UART. bleuart : Implements a simple BLE peripheral that supports the Nordic UART / Serial Port Emulation service","title":"Example NimBLE projects"},{"location":"network/ble/ble_sec/","text":"BLE Security The Bluetooth Low Energy security model includes five distinct security concepts as listed below. For detailed specifications, see BLUETOOTH SPECIFICATION Version 4.2 [Vol 1, Part A]. Pairing : The process for creating one or more shared secret keys. In LE a single link key is generated by combining contributions from each device into a link key used during pairing. Bonding : The act of storing the keys created during pairing for use in subsequent connections in order to form a trusted device pair. Device authentication : Verification that the two devices have the same keys (verify device identity) Encryption : Keeps message confidential. Encryption in Bluetooth LE uses AES-CCM cryptography and is performed in the Controller . Message integrity : Protects against message forgeries. Bluetooth LE uses four association models depending on the I/O capabilities of the devices. Just Works : designed for scenarios where at least one of the devices does not have a display capable of displaying a six digit number nor does it have a keyboard capable of entering six decimal digits. Numeric Comparison : designed for scenarios where both devices are capable of displaying a six digit number and both are capable of having the user enter \"yes\" or \"no\". A good example of this model is the cell phone / PC scenario. Out of Band : designed for scenarios where an Out of Band mechanism is used to both discover the devices as well as to exchange or transfer cryptographic numbers used in the pairing process. Passkey Entry : designed for the scenario where one device has input capability but does not have the capability to display six digits and the other device has output capabilities. A good example of this model is the PC and keyboard scenario. Key Generation Key generation for all purposes in Bluetooth LE is performed by the Host on each LE device independent of any other LE device. Privacy Feature Bluetooth LE supports an optional feature during connection mode and connection procedures that reduces the ability to track a LE device over a period of time by changing the Bluetooth device address on a frequent basis. There are two variants of the privacy feature. In the first variant, private addresses are resolved and generated by the Host . In the second variant, private addresses are resolved and generated by the Controller without involving the Host after the Host provides the Controller device identity information. The Host may provide the Controller with a complete resolving list or a subset of the resolving list. Device filtering becomes possible in the second variant when address resolution is performed in the Controller because the peer\u2019s device identity address can be resolved prior to checking whether it is in the white list. Note : When address resolution is performed exclusively in the Host, a device may experience increased power consumption because device filtering must be disabled. For more details on the privacy feature, refer to BLUETOOTH SPECIFICATION Version 4.2 [Vol 3, Part C] (Published 02 December 2014), Page 592.","title":"NimBLE Security"},{"location":"network/ble/ble_sec/#ble-security","text":"The Bluetooth Low Energy security model includes five distinct security concepts as listed below. For detailed specifications, see BLUETOOTH SPECIFICATION Version 4.2 [Vol 1, Part A]. Pairing : The process for creating one or more shared secret keys. In LE a single link key is generated by combining contributions from each device into a link key used during pairing. Bonding : The act of storing the keys created during pairing for use in subsequent connections in order to form a trusted device pair. Device authentication : Verification that the two devices have the same keys (verify device identity) Encryption : Keeps message confidential. Encryption in Bluetooth LE uses AES-CCM cryptography and is performed in the Controller . Message integrity : Protects against message forgeries. Bluetooth LE uses four association models depending on the I/O capabilities of the devices. Just Works : designed for scenarios where at least one of the devices does not have a display capable of displaying a six digit number nor does it have a keyboard capable of entering six decimal digits. Numeric Comparison : designed for scenarios where both devices are capable of displaying a six digit number and both are capable of having the user enter \"yes\" or \"no\". A good example of this model is the cell phone / PC scenario. Out of Band : designed for scenarios where an Out of Band mechanism is used to both discover the devices as well as to exchange or transfer cryptographic numbers used in the pairing process. Passkey Entry : designed for the scenario where one device has input capability but does not have the capability to display six digits and the other device has output capabilities. A good example of this model is the PC and keyboard scenario.","title":"BLE Security"},{"location":"network/ble/ble_sec/#key-generation","text":"Key generation for all purposes in Bluetooth LE is performed by the Host on each LE device independent of any other LE device.","title":"Key Generation"},{"location":"network/ble/ble_sec/#privacy-feature","text":"Bluetooth LE supports an optional feature during connection mode and connection procedures that reduces the ability to track a LE device over a period of time by changing the Bluetooth device address on a frequent basis. There are two variants of the privacy feature. In the first variant, private addresses are resolved and generated by the Host . In the second variant, private addresses are resolved and generated by the Controller without involving the Host after the Host provides the Controller device identity information. The Host may provide the Controller with a complete resolving list or a subset of the resolving list. Device filtering becomes possible in the second variant when address resolution is performed in the Controller because the peer\u2019s device identity address can be resolved prior to checking whether it is in the white list. Note : When address resolution is performed exclusively in the Host, a device may experience increased power consumption because device filtering must be disabled. For more details on the privacy feature, refer to BLUETOOTH SPECIFICATION Version 4.2 [Vol 3, Part C] (Published 02 December 2014), Page 592.","title":"Privacy Feature"},{"location":"network/ble/nimble_setup/","text":"Set up a NimBLE application This tutorial explains how to set up an application using the NimBLE stack. The end result will be a framework that you can use to create your own BLE application using the nimble stack. This tutorial assumes that you have already installed the newt tool and are familiar with its concepts. Create the application directory You start by creating a project space for your own application work using the Newt tool ( my_proj1 in this example) and installing all the additional apps and libraries available by adding the repo apache-mynewt-core . See the tutorial on adding a repo for more on working with repos. ~/dev$ newt new my_proj1 Downloading project skeleton from apache/incubator-mynewt-blinky... Installing skeleton in my_proj1... Project my_proj1 successfully created. ~/dev$ tree my_proj1 my_proj1 \u251c\u2500\u2500 DISCLAIMER \u251c\u2500\u2500 LICENSE \u251c\u2500\u2500 NOTICE \u251c\u2500\u2500 README.md \u251c\u2500\u2500 apps \u2502 \u2514\u2500\u2500 blinky \u2502 \u251c\u2500\u2500 pkg.yml \u2502 \u2514\u2500\u2500 src \u2502 \u2514\u2500\u2500 main.c \u251c\u2500\u2500 project.yml \u2514\u2500\u2500 targets \u251c\u2500\u2500 my_blinky_sim \u2502 \u251c\u2500\u2500 pkg.yml \u2502 \u2514\u2500\u2500 target.yml \u2514\u2500\u2500 unittest \u251c\u2500\u2500 pkg.yml \u2514\u2500\u2500 target.yml 6 directories, 11 files ~/dev$ cd my_proj1 ~/dev/my_proj1$ newt install apache-mynewt-core ~/dev/my_proj1$ tree . \u251c\u2500\u2500 DISCLAIMER \u251c\u2500\u2500 LICENSE \u251c\u2500\u2500 NOTICE \u251c\u2500\u2500 README.md \u251c\u2500\u2500 apps \u2502 \u2514\u2500\u2500 blinky \u2502 \u251c\u2500\u2500 pkg.yml \u2502 \u2514\u2500\u2500 src \u2502 \u2514\u2500\u2500 main.c \u251c\u2500\u2500 project.state \u251c\u2500\u2500 project.yml \u251c\u2500\u2500 repos \u2502 \u2514\u2500\u2500 apache-mynewt-core \u2502 \u251c\u2500\u2500 DISCLAIMER \u2502 \u251c\u2500\u2500 LICENSE \u2502 \u251c\u2500\u2500 NOTICE \u2502 \u251c\u2500\u2500 README.md \u2502 \u251c\u2500\u2500 RELEASE_NOTES.md \u2502 \u251c\u2500\u2500 apps \u2502 \u2502 \u251c\u2500\u2500 bleprph \u2502 \u2502 \u2502 \u2514\u2500\u2500 src \u2502 \u2502 \u2502 \u251c\u2500\u2500 bleprph.h \u2502 \u2502 \u2502 \u251c\u2500\u2500 gatt_svr.c \u2502 \u2502 \u2502 \u2514\u2500\u2500 main.c \u2502 \u2502 \u251c\u2500\u2500 bletest \u2502 \u2502 \u2502 \u251c\u2500\u2500 pkg.yml \u2502 \u2502 \u2502 \u2514\u2500\u2500 src \u2502 \u2502 \u2502 \u2514\u2500\u2500 main.c \u2502 \u2502 \u251c\u2500\u2500 bletiny \u2502 \u2502 \u2502 \u251c\u2500\u2500 pkg.yml \u2502 \u2502 \u2502 \u2514\u2500\u2500 src \u2502 \u2502 \u2502 \u251c\u2500\u2500 bletiny_priv.h \u2502 \u2502 \u2502 \u251c\u2500\u2500 cmd.c \u2502 \u2502 \u2502 \u251c\u2500\u2500 main.c \u2502 \u2502 \u2502 \u251c\u2500\u2500 parse.c \u2502 \u2502 \u2502 \u2514\u2500\u2500 periph.c <snip> 232 directories, 846 files It's time to build your own app using one or more of the example apps available in the repo apache-mynewt-core . ~/dev/my_proj1$ ls repos/apache-mynewt-core/apps bleprph bletiny boot luatest test bletest blinky ffs2native slinky At the very least your app must contain a main() function and a pkg.yml file. Use the following steps to create minimal ... 1. Create the app directory structure. ~/dev/my_proj1$ mkdir -p apps/ble_app/src 2. Paste the following contents into apps/ble_app/pkg.yml . pkg.name: apps/ble_app pkg.type: app pkg.deps: - \"@apache-mynewt-core/kernel/os\" - \"@apache-mynewt-core/hw/hal\" - \"@apache-mynewt-core/sys/console/full\" - \"@apache-mynewt-core/sys/log/full\" - \"@apache-mynewt-core/sys/stats/full\" - \"@apache-mynewt-core/net/nimble/transport/ram\" - \"@apache-mynewt-core/net/nimble/controller\" - \"@apache-mynewt-core/net/nimble/host\" 3. Paste the following contents into apps/ble_app/src/main.c . #include <assert.h> #include \"os/os.h\" int main ( void ) { /* Initialize OS */ os_init ( NULL ); /* Start the OS */ os_start (); /* os_start should never return. If it does, this should be an error */ assert ( 0 ); } In this main() all we are doing is initializing the Mynewt OS and starting it. Create the target Now you have to create the target that you will use to build your application. We will call this target \"ble_tgt\". Type the newt target create ble_tgt command. You should get this: ~/dev/my_proj1$ newt target create ble_tgt Target targets/ble_tgt successfully created What this command just did was to create a directory called ble_tgt in the targets directory of your project. Two files are created in that directory: pkg.yml and target.yml. The target is not yet complete though! We need to set some target variables for this project. Currently, the nimble stack has been ported to the Nordic nrf5x chipsets; specifically the nrf51 and nrf52. This application will use the nrf52 but we will also show the setup for the nrf51 in case your project uses that chip. Here is the command you will need to set up your target for the nrf52: ~/dev/my_proj1$ newt target set ble_tgt \\ app=apps/ble_app \\ bsp=@apache-mynewt-core/hw/bsp/nrf52pdk \\ build_profile=optimized Target targets/ble_tgt successfully set target.app to apps/ble_app Target targets/ble_tgt successfully set target.bsp to @apache-mynewt-core/hw/bsp/nrf52pdk Target targets/ble_tgt successfully set target.build_profile to optimized Here is the command you will need to set up your target for the nrf51: ~/dev/my_proj1$ newt target set ble_tgt \\ app=apps/ble_app \\ bsp=@apache-mynewt-core/hw/bsp/nrf51dk \\ build_profile=optimized Target targets/ble_tgt successfully set target.app to apps/ble_app Target targets/ble_tgt successfully set target.bsp to @apache-mynewt-core/hw/bsp/nrf51dk Target targets/ble_tgt successfully set target.build_profile to optimized Nimble stack initialization There are certain stack initialization steps that are required for a BLE application to be up and running. If you are running a canned example (e.g. bletiny), these steps are already done for you. When you are writing your own app, you may want to assign different initial values or initialize additional packages that you may have added to your project or written yourself. Details of the initialization step requirements are covered in Initialize Stack step. Building the application Now that we have created the application and the target we can build it and test it out. The command you need to run is the newt build command with the target we created ( ble_tgt ). The output will show the files being compiled and linked. You should see this when all is done (except for the ... of course): ~/dev/my_proj1$ newt build ble_tgt ... Archiving os.a Compiling cons_fmt.c Compiling cons_tty.c Archiving full.a Linking ble_app.elf App successfully built: /Users/wes/dev/my_proj1/bin/ble_tgt/apps/ble_app/ble_app.elf Conclusion You now have a fully functional BLE app (never mind the fact that it doesn't actually do anything yet!). With all the necessary infrastructure in place, you can now start turning this into a real application. Additional tutorials with focus on adding application-layer functionality to your Nimble application will be coming soon. In the meantime, you might get some inspiration from apache-mynewt-core's example Nimble apps. These apps can be found at the below locations, relative to your project's base directory: repos/apache-mynewt-core/apps/bleprph repos/apache-mynewt-core/apps/bletiny","title":"Set up application"},{"location":"network/ble/nimble_setup/#set-up-a-nimble-application","text":"This tutorial explains how to set up an application using the NimBLE stack. The end result will be a framework that you can use to create your own BLE application using the nimble stack. This tutorial assumes that you have already installed the newt tool and are familiar with its concepts.","title":"Set up a NimBLE application"},{"location":"network/ble/nimble_setup/#create-the-application-directory","text":"You start by creating a project space for your own application work using the Newt tool ( my_proj1 in this example) and installing all the additional apps and libraries available by adding the repo apache-mynewt-core . See the tutorial on adding a repo for more on working with repos. ~/dev$ newt new my_proj1 Downloading project skeleton from apache/incubator-mynewt-blinky... Installing skeleton in my_proj1... Project my_proj1 successfully created. ~/dev$ tree my_proj1 my_proj1 \u251c\u2500\u2500 DISCLAIMER \u251c\u2500\u2500 LICENSE \u251c\u2500\u2500 NOTICE \u251c\u2500\u2500 README.md \u251c\u2500\u2500 apps \u2502 \u2514\u2500\u2500 blinky \u2502 \u251c\u2500\u2500 pkg.yml \u2502 \u2514\u2500\u2500 src \u2502 \u2514\u2500\u2500 main.c \u251c\u2500\u2500 project.yml \u2514\u2500\u2500 targets \u251c\u2500\u2500 my_blinky_sim \u2502 \u251c\u2500\u2500 pkg.yml \u2502 \u2514\u2500\u2500 target.yml \u2514\u2500\u2500 unittest \u251c\u2500\u2500 pkg.yml \u2514\u2500\u2500 target.yml 6 directories, 11 files ~/dev$ cd my_proj1 ~/dev/my_proj1$ newt install apache-mynewt-core ~/dev/my_proj1$ tree . \u251c\u2500\u2500 DISCLAIMER \u251c\u2500\u2500 LICENSE \u251c\u2500\u2500 NOTICE \u251c\u2500\u2500 README.md \u251c\u2500\u2500 apps \u2502 \u2514\u2500\u2500 blinky \u2502 \u251c\u2500\u2500 pkg.yml \u2502 \u2514\u2500\u2500 src \u2502 \u2514\u2500\u2500 main.c \u251c\u2500\u2500 project.state \u251c\u2500\u2500 project.yml \u251c\u2500\u2500 repos \u2502 \u2514\u2500\u2500 apache-mynewt-core \u2502 \u251c\u2500\u2500 DISCLAIMER \u2502 \u251c\u2500\u2500 LICENSE \u2502 \u251c\u2500\u2500 NOTICE \u2502 \u251c\u2500\u2500 README.md \u2502 \u251c\u2500\u2500 RELEASE_NOTES.md \u2502 \u251c\u2500\u2500 apps \u2502 \u2502 \u251c\u2500\u2500 bleprph \u2502 \u2502 \u2502 \u2514\u2500\u2500 src \u2502 \u2502 \u2502 \u251c\u2500\u2500 bleprph.h \u2502 \u2502 \u2502 \u251c\u2500\u2500 gatt_svr.c \u2502 \u2502 \u2502 \u2514\u2500\u2500 main.c \u2502 \u2502 \u251c\u2500\u2500 bletest \u2502 \u2502 \u2502 \u251c\u2500\u2500 pkg.yml \u2502 \u2502 \u2502 \u2514\u2500\u2500 src \u2502 \u2502 \u2502 \u2514\u2500\u2500 main.c \u2502 \u2502 \u251c\u2500\u2500 bletiny \u2502 \u2502 \u2502 \u251c\u2500\u2500 pkg.yml \u2502 \u2502 \u2502 \u2514\u2500\u2500 src \u2502 \u2502 \u2502 \u251c\u2500\u2500 bletiny_priv.h \u2502 \u2502 \u2502 \u251c\u2500\u2500 cmd.c \u2502 \u2502 \u2502 \u251c\u2500\u2500 main.c \u2502 \u2502 \u2502 \u251c\u2500\u2500 parse.c \u2502 \u2502 \u2502 \u2514\u2500\u2500 periph.c <snip> 232 directories, 846 files It's time to build your own app using one or more of the example apps available in the repo apache-mynewt-core . ~/dev/my_proj1$ ls repos/apache-mynewt-core/apps bleprph bletiny boot luatest test bletest blinky ffs2native slinky At the very least your app must contain a main() function and a pkg.yml file. Use the following steps to create minimal ... 1. Create the app directory structure. ~/dev/my_proj1$ mkdir -p apps/ble_app/src 2. Paste the following contents into apps/ble_app/pkg.yml . pkg.name: apps/ble_app pkg.type: app pkg.deps: - \"@apache-mynewt-core/kernel/os\" - \"@apache-mynewt-core/hw/hal\" - \"@apache-mynewt-core/sys/console/full\" - \"@apache-mynewt-core/sys/log/full\" - \"@apache-mynewt-core/sys/stats/full\" - \"@apache-mynewt-core/net/nimble/transport/ram\" - \"@apache-mynewt-core/net/nimble/controller\" - \"@apache-mynewt-core/net/nimble/host\" 3. Paste the following contents into apps/ble_app/src/main.c . #include <assert.h> #include \"os/os.h\" int main ( void ) { /* Initialize OS */ os_init ( NULL ); /* Start the OS */ os_start (); /* os_start should never return. If it does, this should be an error */ assert ( 0 ); } In this main() all we are doing is initializing the Mynewt OS and starting it.","title":"Create the application directory"},{"location":"network/ble/nimble_setup/#create-the-target","text":"Now you have to create the target that you will use to build your application. We will call this target \"ble_tgt\". Type the newt target create ble_tgt command. You should get this: ~/dev/my_proj1$ newt target create ble_tgt Target targets/ble_tgt successfully created What this command just did was to create a directory called ble_tgt in the targets directory of your project. Two files are created in that directory: pkg.yml and target.yml. The target is not yet complete though! We need to set some target variables for this project. Currently, the nimble stack has been ported to the Nordic nrf5x chipsets; specifically the nrf51 and nrf52. This application will use the nrf52 but we will also show the setup for the nrf51 in case your project uses that chip. Here is the command you will need to set up your target for the nrf52: ~/dev/my_proj1$ newt target set ble_tgt \\ app=apps/ble_app \\ bsp=@apache-mynewt-core/hw/bsp/nrf52pdk \\ build_profile=optimized Target targets/ble_tgt successfully set target.app to apps/ble_app Target targets/ble_tgt successfully set target.bsp to @apache-mynewt-core/hw/bsp/nrf52pdk Target targets/ble_tgt successfully set target.build_profile to optimized Here is the command you will need to set up your target for the nrf51: ~/dev/my_proj1$ newt target set ble_tgt \\ app=apps/ble_app \\ bsp=@apache-mynewt-core/hw/bsp/nrf51dk \\ build_profile=optimized Target targets/ble_tgt successfully set target.app to apps/ble_app Target targets/ble_tgt successfully set target.bsp to @apache-mynewt-core/hw/bsp/nrf51dk Target targets/ble_tgt successfully set target.build_profile to optimized","title":"Create the target"},{"location":"network/ble/nimble_setup/#nimble-stack-initialization","text":"There are certain stack initialization steps that are required for a BLE application to be up and running. If you are running a canned example (e.g. bletiny), these steps are already done for you. When you are writing your own app, you may want to assign different initial values or initialize additional packages that you may have added to your project or written yourself. Details of the initialization step requirements are covered in Initialize Stack step.","title":"Nimble stack initialization"},{"location":"network/ble/nimble_setup/#building-the-application","text":"Now that we have created the application and the target we can build it and test it out. The command you need to run is the newt build command with the target we created ( ble_tgt ). The output will show the files being compiled and linked. You should see this when all is done (except for the ... of course): ~/dev/my_proj1$ newt build ble_tgt ... Archiving os.a Compiling cons_fmt.c Compiling cons_tty.c Archiving full.a Linking ble_app.elf App successfully built: /Users/wes/dev/my_proj1/bin/ble_tgt/apps/ble_app/ble_app.elf","title":"Building the application"},{"location":"network/ble/nimble_setup/#conclusion","text":"You now have a fully functional BLE app (never mind the fact that it doesn't actually do anything yet!). With all the necessary infrastructure in place, you can now start turning this into a real application. Additional tutorials with focus on adding application-layer functionality to your Nimble application will be coming soon. In the meantime, you might get some inspiration from apache-mynewt-core's example Nimble apps. These apps can be found at the below locations, relative to your project's base directory: repos/apache-mynewt-core/apps/bleprph repos/apache-mynewt-core/apps/bletiny","title":"Conclusion"},{"location":"network/ble/ble_hs/ble_hs/","text":"NimBLE Host Introduction At a high level, the NimBLE stack is divided into two components: Host Controller This document is an API reference for the host component. If you are interested in the general structure of the NimBLE stack and its non-host components, you might want to read the BLE introduction . The host sits directly below the application, and it serves as the interface to the application for all BLE operations. Reference NimBLE Host Return Codes Initialization and Configuration Generic Access Protocol (GAP) Generic Attribute Profile (GATT) Client Generic Attribute Profile (GATT) Server Identity Other","title":"toc"},{"location":"network/ble/ble_hs/ble_hs/#nimble-host","text":"","title":"NimBLE Host"},{"location":"network/ble/ble_hs/ble_hs/#introduction","text":"At a high level, the NimBLE stack is divided into two components: Host Controller This document is an API reference for the host component. If you are interested in the general structure of the NimBLE stack and its non-host components, you might want to read the BLE introduction . The host sits directly below the application, and it serves as the interface to the application for all BLE operations.","title":"Introduction"},{"location":"network/ble/ble_hs/ble_hs/#reference","text":"NimBLE Host Return Codes Initialization and Configuration Generic Access Protocol (GAP) Generic Attribute Profile (GATT) Client Generic Attribute Profile (GATT) Server Identity Other","title":"Reference"},{"location":"network/ble/ble_hs/ble_hs_return_codes/","text":"NimBLE Host Return Codes Introduction Summary Example Return Code Reference Return codes - Core Return codes - ATT Return codes - HCI Return codes - L2CAP Return codes - Security manager (us) Return codes - Security manager (peer) Introduction Summary The NimBLE host reports status to the application via a set of return codes. The host encompasses several layers of the Bluetooth specification that each defines its own set of status codes. Rather than \"abstract away\" information from lower layers that the application developer might find useful, the NimBLE host aims to indicate precisely what happened when something fails. Consequently, the host utilizes a rather large set of return codes. A return code of 0 indicates success. For failure conditions, the return codes are partitioned into five separate sets: | Set | Condition | Notes| |-----|-------------| | Core | Errors detected internally by the NimBLE host. | | ATT | The ATT server has reported a failure via the transmission of an ATT Error Response. The return code corresponds to the value of the Error Code field in the response. | | HCI | The controller has reported an error to the host via a command complete or command status HCI event. The return code corresponds to the value of the Status field in the event. | L2CAP | An L2CAP signaling procedure has failed and an L2CAP Command Reject was sent as a result. The return code corresponds to the value of the Reason field in the command. | Security manager (us) | The host detected an error during a security manager procedure and sent a Pairing Failed command to the peer. The return code corresponds to the value of the Reason field in the Pairing Failed command. | | Security manager (peer) | A security manager procedure failed because the peer sent us a Pairing Failed command. The return code corresponds to the value of the Reason field in the Pairing Failed command. | The return codes in the core set are defined by the NimBLE Host. The other sets are defined in the Bluetooth specification; the codes in this latter group are referred to as formal status codes . As defined in the Bluetooth specification, the formal status code sets are not disjoint. That is, they overlap. For example, the spec defines a status code of 1 to have all of the following meanings: Layer Meaning ATT Invalid handle. HCI Unknown HCI command. L2CAP Signalling MTU exceeded. SM Passkey entry failed. Clearly, the host can't just return an unadorned formal status code and expect the application to make sense of it. To resolve this ambiguity, the NimBLE host divides the full range of an int into several subranges. Each subrange corresponds to one of the five return code sets. For example, the ATT set is mapped onto the subrange [0x100, 0x200) . To indicate an ATT error of 3 (write not permitted), the NimBLE host returns a value 0x103 to the application. The host defines a set of convenience macros for converting from a formal status code to NimBLE host status code. These macros are documented in the table below. Macro Status code set Base value BLE_HS_ATT_ERR() ATT 0x100 BLE_HS_HCI_ERR() HCI 0x200 BLE_HS_L2C_ERR() L2CAP 0x300 BLE_HS_SM_US_ERR() Security manager (us) 0x400 BLE_HS_SM_PEER_ERR() Security manager (peer) 0x500 Example The following example demonstrates how an application might determine which error is being reported by the host. In this example, the application performs the GAP encryption procedure and checks the return code. To simplify the example, the application uses a hypothetical my_blocking_enc_proc() function, which blocks until the pairing operation has completed. void encrypt_connection ( uint16_t conn_handle ) { int rc ; /* Perform a blocking GAP encryption procedure. */ rc = my_blocking_enc_proc ( conn_handle ); switch ( rc ) { case 0 : console_printf ( \"success - link successfully encrypted\\n\" ); break ; case BLE_HS_ENOTCONN : console_printf ( \"failure - no connection with handle %d\\n\" , conn_handle ); break ; case BLE_HS_ERR_SM_US_BASE ( BLE_SM_ERR_CONFIRM_MISMATCH ): console_printf ( \"failure - mismatch in peer's confirm and random \" \"commands.\\n\" ); break ; case BLE_HS_ERR_SM_PEER_BASE ( BLE_SM_ERR_CONFIRM_MISMATCH ): console_printf ( \"failure - peer reports mismatch in our confirm and \" \"random commands.\\n\" ); break ; default : console_printf ( \"failure - other error: 0x%04x\\n\" , rc ); break ; } } Return Code Reference Header All NimBLE host return codes are made accessible by including the following header: #include \"host/ble_hs.h\" Return codes - Core The precise meaning of each of these error codes depends on the function that returns it. The API reference for a particular function indicates the conditions under which each of these codes are returned. Value Name Condition 0x00 N/A Success 0x01 BLE_HS_EAGAIN Temporary failure; try again. 0x02 BLE_HS_EALREADY Operation already in progress or completed. 0x03 BLE_HS_EINVAL One or more arguments are invalid. 0x04 BLE_HS_EMSGSIZE The provided buffer is too small. 0x05 BLE_HS_ENOENT No entry matching the specified criteria. 0x06 BLE_HS_ENOMEM Operation failed due to resource exhaustion. 0x07 BLE_HS_ENOTCONN No open connection with the specified handle. 0x08 BLE_HS_ENOTSUP Operation disabled at compile time. 0x09 BLE_HS_EAPP Application callback behaved unexpectedly. 0x0a BLE_HS_EBADDATA Command from peer is invalid. 0x0b BLE_HS_EOS Mynewt OS error. 0x0c BLE_HS_ECONTROLLER Event from controller is invalid. 0x0d BLE_HS_ETIMEOUT Operation timed out. 0x0e BLE_HS_EDONE Operation completed successfully. 0x0f BLE_HS_EBUSY Operation cannot be performed until procedure completes. 0x10 BLE_HS_EREJECT Peer rejected a connection parameter update request. 0x11 BLE_HS_EUNKNOWN Unexpected failure; catch all. 0x12 BLE_HS_EROLE Operation requires different role (e.g., central vs. peripheral). 0x13 BLE_HS_ETIMEOUT_HCI HCI request timed out; controller unresponsive. 0x14 BLE_HS_ENOMEM_EVT Controller failed to send event due to memory exhaustion (combined host-controller only). 0x15 BLE_HS_ENOADDR Operation requires an identity address but none configured. Return codes - ATT NimBLE Value Formal Value Name Condition 0x0101 0x01 BLE_ATT_ERR_INVALID_HANDLE The attribute handle given was not valid on this server. 0x0102 0x02 BLE_ATT_ERR_READ_NOT_PERMITTED The attribute cannot be read. 0x0103 0x03 BLE_ATT_ERR_WRITE_NOT_PERMITTED The attribute cannot be written. 0x0104 0x04 BLE_ATT_ERR_INVALID_PDU The attribute PDU was invalid. 0x0105 0x05 BLE_ATT_ERR_INSUFFICIENT_AUTHEN The attribute requires authentication before it can be read or written. 0x0106 0x06 BLE_ATT_ERR_REQ_NOT_SUPPORTED Attribute server does not support the request received from the client. 0x0107 0x07 BLE_ATT_ERR_INVALID_OFFSET Offset specified was past the end of the attribute. 0x0108 0x08 BLE_ATT_ERR_INSUFFICIENT_AUTHOR The attribute requires authorization before it can be read or written. 0x0109 0x09 BLE_ATT_ERR_PREPARE_QUEUE_FULL Too many prepare writes have been queued. 0x010a 0x0a BLE_ATT_ERR_ATTR_NOT_FOUND No attribute found within the given attribute handle range. 0x010b 0x0b BLE_ATT_ERR_ATTR_NOT_LONG The attribute cannot be read or written using the Read Blob Request. 0x010c 0x0c BLE_ATT_ERR_INSUFFICIENT_KEY_SZ The Encryption Key Size used for encrypting this link is insufficient. 0x010d 0x0d BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN The attribute value length is invalid for the operation. 0x010e 0x0e BLE_ATT_ERR_UNLIKELY The attribute request that was requested has encountered an error that was unlikely, and therefore could not be completed as requested. 0x010f 0x0f BLE_ATT_ERR_INSUFFICIENT_ENC The attribute requires encryption before it can be read or written. 0x0110 0x10 BLE_ATT_ERR_UNSUPPORTED_GROUP The attribute type is not a supported grouping attribute as defined by a higher layer specification. 0x0111 0x11 BLE_ATT_ERR_INSUFFICIENT_RES Insufficient Resources to complete the request. Return codes - HCI NimBLE Value Formal Value Name Condition 0x0201 0x01 BLE_ERR_UNKNOWN_HCI_CMD Unknown HCI Command 0x0202 0x02 BLE_ERR_UNK_CONN_ID Unknown Connection Identifier 0x0203 0x03 BLE_ERR_HW_FAIL Hardware Failure 0x0204 0x04 BLE_ERR_PAGE_TMO Page Timeout 0x0205 0x05 BLE_ERR_AUTH_FAIL Authentication Failure 0x0206 0x06 BLE_ERR_PINKEY_MISSING PIN or Key Missing 0x0207 0x07 BLE_ERR_MEM_CAPACITY Memory Capacity Exceeded 0x0208 0x08 BLE_ERR_CONN_SPVN_TMO Connection Timeout 0x0209 0x09 BLE_ERR_CONN_LIMIT Connection Limit Exceeded 0x020a 0x0a BLE_ERR_SYNCH_CONN_LIMIT Synchronous Connection Limit To A Device Exceeded 0x020b 0x0b BLE_ERR_ACL_CONN_EXISTS ACL Connection Already Exists 0x020c 0x0c BLE_ERR_CMD_DISALLOWED Command Disallowed 0x020d 0x0d BLE_ERR_CONN_REJ_RESOURCES Connection Rejected due to Limited Resources 0x020e 0x0e BLE_ERR_CONN_REJ_SECURITY Connection Rejected Due To Security Reasons 0x020f 0x0f BLE_ERR_CONN_REJ_BD_ADDR Connection Rejected due to Unacceptable BD_ADDR 0x0210 0x10 BLE_ERR_CONN_ACCEPT_TMO Connection Accept Timeout Exceeded 0x0211 0x11 BLE_ERR_UNSUPPORTED Unsupported Feature or Parameter Value 0x0212 0x12 BLE_ERR_INV_HCI_CMD_PARMS Invalid HCI Command Parameters 0x0213 0x13 BLE_ERR_REM_USER_CONN_TERM Remote User Terminated Connection 0x0214 0x14 BLE_ERR_RD_CONN_TERM_RESRCS Remote Device Terminated Connection due to Low Resources 0x0215 0x15 BLE_ERR_RD_CONN_TERM_PWROFF Remote Device Terminated Connection due to Power Off 0x0216 0x16 BLE_ERR_CONN_TERM_LOCAL Connection Terminated By Local Host 0x0217 0x17 BLE_ERR_REPEATED_ATTEMPTS Repeated Attempts 0x0218 0x18 BLE_ERR_NO_PAIRING Pairing Not Allowed 0x0219 0x19 BLE_ERR_UNK_LMP Unknown LMP PDU 0x021a 0x1a BLE_ERR_UNSUPP_REM_FEATURE Unsupported Remote Feature / Unsupported LMP Feature 0x021b 0x1b BLE_ERR_SCO_OFFSET SCO Offset Rejected 0x021c 0x1c BLE_ERR_SCO_ITVL SCO Interval Rejected 0x021d 0x1d BLE_ERR_SCO_AIR_MODE SCO Air Mode Rejected 0x021e 0x1e BLE_ERR_INV_LMP_LL_PARM Invalid LMP Parameters / Invalid LL Parameters 0x021f 0x1f BLE_ERR_UNSPECIFIED Unspecified Error 0x0220 0x20 BLE_ERR_UNSUPP_LMP_LL_PARM Unsupported LMP Parameter Value / Unsupported LL Parameter Value 0x0221 0x21 BLE_ERR_NO_ROLE_CHANGE Role Change Not Allowed 0x0222 0x22 BLE_ERR_LMP_LL_RSP_TMO LMP Response Timeout / LL Response Timeout 0x0223 0x23 BLE_ERR_LMP_COLLISION LMP Error Transaction Collision 0x0224 0x24 BLE_ERR_LMP_PDU LMP PDU Not Allowed 0x0225 0x25 BLE_ERR_ENCRYPTION_MODE Encryption Mode Not Acceptable 0x0226 0x26 BLE_ERR_LINK_KEY_CHANGE Link Key cannot be Changed 0x0227 0x27 BLE_ERR_UNSUPP_QOS Requested QoS Not Supported 0x0228 0x28 BLE_ERR_INSTANT_PASSED Instant Passed 0x0229 0x29 BLE_ERR_UNIT_KEY_PAIRING Pairing With Unit Key Not Supported 0x022a 0x2a BLE_ERR_DIFF_TRANS_COLL Different Transaction Collision 0x022c 0x2c BLE_ERR_QOS_PARM QoS Unacceptable Parameter 0x022d 0x2d BLE_ERR_QOS_REJECTED QoS Rejected 0x022e 0x2e BLE_ERR_CHAN_CLASS Channel Classification Not Supported 0x022f 0x2f BLE_ERR_INSUFFICIENT_SEC Insufficient Security 0x0230 0x30 BLE_ERR_PARM_OUT_OF_RANGE Parameter Out Of Mandatory Range 0x0232 0x32 BLE_ERR_PENDING_ROLE_SW Role Switch Pending 0x0234 0x34 BLE_ERR_RESERVED_SLOT Reserved Slot Violation 0x0235 0x35 BLE_ERR_ROLE_SW_FAIL Role Switch Failed 0x0236 0x36 BLE_ERR_INQ_RSP_TOO_BIG Extended Inquiry Response Too Large 0x0237 0x37 BLE_ERR_SEC_SIMPLE_PAIR Secure Simple Pairing Not Supported By Host 0x0238 0x38 BLE_ERR_HOST_BUSY_PAIR Host Busy - Pairing 0x0239 0x39 BLE_ERR_CONN_REJ_CHANNEL Connection Rejected due to No Suitable Channel Found 0x023a 0x3a BLE_ERR_CTLR_BUSY Controller Busy 0x023b 0x3b BLE_ERR_CONN_PARMS Unacceptable Connection Parameters 0x023c 0x3c BLE_ERR_DIR_ADV_TMO Directed Advertising Timeout 0x023d 0x3d BLE_ERR_CONN_TERM_MIC Connection Terminated due to MIC Failure 0x023e 0x3e BLE_ERR_CONN_ESTABLISHMENT Connection Failed to be Established 0x023f 0x3f BLE_ERR_MAC_CONN_FAIL MAC Connection Failed 0x0240 0x40 BLE_ERR_COARSE_CLK_ADJ Coarse Clock Adjustment Rejected but Will Try to Adjust Using Clock Dragging Return codes - L2CAP NimBLE Value Formal Value Name Condition 0x0300 0x00 BLE_L2CAP_SIG_ERR_CMD_NOT_UNDERSTOOD Invalid or unsupported incoming L2CAP sig command. 0x0301 0x01 BLE_L2CAP_SIG_ERR_MTU_EXCEEDED Incoming packet too large. 0x0302 0x02 BLE_L2CAP_SIG_ERR_INVALID_CID No channel with specified ID. Return codes - Security manager (us) NimBLE Value Formal Value Name Condition 0x0401 0x01 BLE_SM_ERR_PASSKEY The user input of passkey failed, for example, the user cancelled the operation. 0x0402 0x02 BLE_SM_ERR_OOB The OOB data is not available. 0x0403 0x03 BLE_SM_ERR_AUTHREQ The pairing procedure cannot be performed as authentication requirements cannot be met due to IO capabilities of one or both devices. 0x0404 0x04 BLE_SM_ERR_CONFIRM_MISMATCH The confirm value does not match the calculated compare value. 0x0405 0x05 BLE_SM_ERR_PAIR_NOT_SUPP Pairing is not supported by the device. 0x0406 0x06 BLE_SM_ERR_ENC_KEY_SZ The resultant encryption key size is insufficient for the security requirements of this device. 0x0407 0x07 BLE_SM_ERR_CMD_NOT_SUPP The SMP command received is not supported on this device. 0x0408 0x08 BLE_SM_ERR_UNSPECIFIED Pairing failed due to an unspecified reason. 0x0409 0x09 BLE_SM_ERR_REPEATED Pairing or authentication procedure is disallowed because too little time has elapsed since last pairing request or security request. 0x040a 0x0a BLE_SM_ERR_INVAL The Invalid Parameters error code indicates that the command length is invalid or that a parameter is outside of the specified range. 0x040b 0x0b BLE_SM_ERR_DHKEY Indicates to the remote device that the DHKey Check value received doesn\u2019t match the one calculated by the local device. 0x040c 0x0c BLE_SM_ERR_NUMCMP Indicates that the confirm values in the numeric comparison protocol do not match. 0x040d 0x0d BLE_SM_ERR_ALREADY Indicates that the pairing over the LE transport failed due to a Pairing Request sent over the BR/EDR transport in process. 0x040e 0x0e BLE_SM_ERR_CROSS_TRANS Indicates that the BR/EDR Link Key generated on the BR/EDR transport cannot be used to derive and distribute keys for the LE transport. Return codes - Security manager (peer) NimBLE Value Formal Value Name Condition 0x0501 0x01 BLE_SM_ERR_PASSKEY The user input of passkey failed, for example, the user cancelled the operation. 0x0502 0x02 BLE_SM_ERR_OOB The OOB data is not available. 0x0503 0x03 BLE_SM_ERR_AUTHREQ The pairing procedure cannot be performed as authentication requirements cannot be met due to IO capabilities of one or both devices. 0x0504 0x04 BLE_SM_ERR_CONFIRM_MISMATCH The confirm value does not match the calculated compare value. 0x0505 0x05 BLE_SM_ERR_PAIR_NOT_SUPP Pairing is not supported by the device. 0x0506 0x06 BLE_SM_ERR_ENC_KEY_SZ The resultant encryption key size is insufficient for the security requirements of this device. 0x0507 0x07 BLE_SM_ERR_CMD_NOT_SUPP The SMP command received is not supported on this device. 0x0508 0x08 BLE_SM_ERR_UNSPECIFIED Pairing failed due to an unspecified reason. 0x0509 0x09 BLE_SM_ERR_REPEATED Pairing or authentication procedure is disallowed because too little time has elapsed since last pairing request or security request. 0x050a 0x0a BLE_SM_ERR_INVAL The Invalid Parameters error code indicates that the command length is invalid or that a parameter is outside of the specified range. 0x050b 0x0b BLE_SM_ERR_DHKEY Indicates to the remote device that the DHKey Check value received doesn\u2019t match the one calculated by the local device. 0x050c 0x0c BLE_SM_ERR_NUMCMP Indicates that the confirm values in the numeric comparison protocol do not match. 0x050d 0x0d BLE_SM_ERR_ALREADY Indicates that the pairing over the LE transport failed due to a Pairing Request sent over the BR/EDR transport in process. 0x050e 0x0e BLE_SM_ERR_CROSS_TRANS Indicates that the BR/EDR Link Key generated on the BR/EDR transport cannot be used to derive and distribute keys for the LE transport.","title":"Return codes"},{"location":"network/ble/ble_hs/ble_hs_return_codes/#nimble-host-return-codes","text":"Introduction Summary Example Return Code Reference Return codes - Core Return codes - ATT Return codes - HCI Return codes - L2CAP Return codes - Security manager (us) Return codes - Security manager (peer)","title":"NimBLE Host Return Codes"},{"location":"network/ble/ble_hs/ble_hs_return_codes/#introduction","text":"","title":"Introduction"},{"location":"network/ble/ble_hs/ble_hs_return_codes/#summary","text":"The NimBLE host reports status to the application via a set of return codes. The host encompasses several layers of the Bluetooth specification that each defines its own set of status codes. Rather than \"abstract away\" information from lower layers that the application developer might find useful, the NimBLE host aims to indicate precisely what happened when something fails. Consequently, the host utilizes a rather large set of return codes. A return code of 0 indicates success. For failure conditions, the return codes are partitioned into five separate sets: | Set | Condition | Notes| |-----|-------------| | Core | Errors detected internally by the NimBLE host. | | ATT | The ATT server has reported a failure via the transmission of an ATT Error Response. The return code corresponds to the value of the Error Code field in the response. | | HCI | The controller has reported an error to the host via a command complete or command status HCI event. The return code corresponds to the value of the Status field in the event. | L2CAP | An L2CAP signaling procedure has failed and an L2CAP Command Reject was sent as a result. The return code corresponds to the value of the Reason field in the command. | Security manager (us) | The host detected an error during a security manager procedure and sent a Pairing Failed command to the peer. The return code corresponds to the value of the Reason field in the Pairing Failed command. | | Security manager (peer) | A security manager procedure failed because the peer sent us a Pairing Failed command. The return code corresponds to the value of the Reason field in the Pairing Failed command. | The return codes in the core set are defined by the NimBLE Host. The other sets are defined in the Bluetooth specification; the codes in this latter group are referred to as formal status codes . As defined in the Bluetooth specification, the formal status code sets are not disjoint. That is, they overlap. For example, the spec defines a status code of 1 to have all of the following meanings: Layer Meaning ATT Invalid handle. HCI Unknown HCI command. L2CAP Signalling MTU exceeded. SM Passkey entry failed. Clearly, the host can't just return an unadorned formal status code and expect the application to make sense of it. To resolve this ambiguity, the NimBLE host divides the full range of an int into several subranges. Each subrange corresponds to one of the five return code sets. For example, the ATT set is mapped onto the subrange [0x100, 0x200) . To indicate an ATT error of 3 (write not permitted), the NimBLE host returns a value 0x103 to the application. The host defines a set of convenience macros for converting from a formal status code to NimBLE host status code. These macros are documented in the table below. Macro Status code set Base value BLE_HS_ATT_ERR() ATT 0x100 BLE_HS_HCI_ERR() HCI 0x200 BLE_HS_L2C_ERR() L2CAP 0x300 BLE_HS_SM_US_ERR() Security manager (us) 0x400 BLE_HS_SM_PEER_ERR() Security manager (peer) 0x500","title":"Summary"},{"location":"network/ble/ble_hs/ble_hs_return_codes/#example","text":"The following example demonstrates how an application might determine which error is being reported by the host. In this example, the application performs the GAP encryption procedure and checks the return code. To simplify the example, the application uses a hypothetical my_blocking_enc_proc() function, which blocks until the pairing operation has completed. void encrypt_connection ( uint16_t conn_handle ) { int rc ; /* Perform a blocking GAP encryption procedure. */ rc = my_blocking_enc_proc ( conn_handle ); switch ( rc ) { case 0 : console_printf ( \"success - link successfully encrypted\\n\" ); break ; case BLE_HS_ENOTCONN : console_printf ( \"failure - no connection with handle %d\\n\" , conn_handle ); break ; case BLE_HS_ERR_SM_US_BASE ( BLE_SM_ERR_CONFIRM_MISMATCH ): console_printf ( \"failure - mismatch in peer's confirm and random \" \"commands.\\n\" ); break ; case BLE_HS_ERR_SM_PEER_BASE ( BLE_SM_ERR_CONFIRM_MISMATCH ): console_printf ( \"failure - peer reports mismatch in our confirm and \" \"random commands.\\n\" ); break ; default : console_printf ( \"failure - other error: 0x%04x\\n\" , rc ); break ; } }","title":"Example"},{"location":"network/ble/ble_hs/ble_hs_return_codes/#return-code-reference","text":"","title":"Return Code Reference"},{"location":"network/ble/ble_hs/ble_hs_return_codes/#header","text":"All NimBLE host return codes are made accessible by including the following header: #include \"host/ble_hs.h\"","title":"Header"},{"location":"network/ble/ble_hs/ble_hs_return_codes/#return-codes-core","text":"The precise meaning of each of these error codes depends on the function that returns it. The API reference for a particular function indicates the conditions under which each of these codes are returned. Value Name Condition 0x00 N/A Success 0x01 BLE_HS_EAGAIN Temporary failure; try again. 0x02 BLE_HS_EALREADY Operation already in progress or completed. 0x03 BLE_HS_EINVAL One or more arguments are invalid. 0x04 BLE_HS_EMSGSIZE The provided buffer is too small. 0x05 BLE_HS_ENOENT No entry matching the specified criteria. 0x06 BLE_HS_ENOMEM Operation failed due to resource exhaustion. 0x07 BLE_HS_ENOTCONN No open connection with the specified handle. 0x08 BLE_HS_ENOTSUP Operation disabled at compile time. 0x09 BLE_HS_EAPP Application callback behaved unexpectedly. 0x0a BLE_HS_EBADDATA Command from peer is invalid. 0x0b BLE_HS_EOS Mynewt OS error. 0x0c BLE_HS_ECONTROLLER Event from controller is invalid. 0x0d BLE_HS_ETIMEOUT Operation timed out. 0x0e BLE_HS_EDONE Operation completed successfully. 0x0f BLE_HS_EBUSY Operation cannot be performed until procedure completes. 0x10 BLE_HS_EREJECT Peer rejected a connection parameter update request. 0x11 BLE_HS_EUNKNOWN Unexpected failure; catch all. 0x12 BLE_HS_EROLE Operation requires different role (e.g., central vs. peripheral). 0x13 BLE_HS_ETIMEOUT_HCI HCI request timed out; controller unresponsive. 0x14 BLE_HS_ENOMEM_EVT Controller failed to send event due to memory exhaustion (combined host-controller only). 0x15 BLE_HS_ENOADDR Operation requires an identity address but none configured.","title":"Return codes - Core"},{"location":"network/ble/ble_hs/ble_hs_return_codes/#return-codes-att","text":"NimBLE Value Formal Value Name Condition 0x0101 0x01 BLE_ATT_ERR_INVALID_HANDLE The attribute handle given was not valid on this server. 0x0102 0x02 BLE_ATT_ERR_READ_NOT_PERMITTED The attribute cannot be read. 0x0103 0x03 BLE_ATT_ERR_WRITE_NOT_PERMITTED The attribute cannot be written. 0x0104 0x04 BLE_ATT_ERR_INVALID_PDU The attribute PDU was invalid. 0x0105 0x05 BLE_ATT_ERR_INSUFFICIENT_AUTHEN The attribute requires authentication before it can be read or written. 0x0106 0x06 BLE_ATT_ERR_REQ_NOT_SUPPORTED Attribute server does not support the request received from the client. 0x0107 0x07 BLE_ATT_ERR_INVALID_OFFSET Offset specified was past the end of the attribute. 0x0108 0x08 BLE_ATT_ERR_INSUFFICIENT_AUTHOR The attribute requires authorization before it can be read or written. 0x0109 0x09 BLE_ATT_ERR_PREPARE_QUEUE_FULL Too many prepare writes have been queued. 0x010a 0x0a BLE_ATT_ERR_ATTR_NOT_FOUND No attribute found within the given attribute handle range. 0x010b 0x0b BLE_ATT_ERR_ATTR_NOT_LONG The attribute cannot be read or written using the Read Blob Request. 0x010c 0x0c BLE_ATT_ERR_INSUFFICIENT_KEY_SZ The Encryption Key Size used for encrypting this link is insufficient. 0x010d 0x0d BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN The attribute value length is invalid for the operation. 0x010e 0x0e BLE_ATT_ERR_UNLIKELY The attribute request that was requested has encountered an error that was unlikely, and therefore could not be completed as requested. 0x010f 0x0f BLE_ATT_ERR_INSUFFICIENT_ENC The attribute requires encryption before it can be read or written. 0x0110 0x10 BLE_ATT_ERR_UNSUPPORTED_GROUP The attribute type is not a supported grouping attribute as defined by a higher layer specification. 0x0111 0x11 BLE_ATT_ERR_INSUFFICIENT_RES Insufficient Resources to complete the request.","title":"Return codes - ATT"},{"location":"network/ble/ble_hs/ble_hs_return_codes/#return-codes-hci","text":"NimBLE Value Formal Value Name Condition 0x0201 0x01 BLE_ERR_UNKNOWN_HCI_CMD Unknown HCI Command 0x0202 0x02 BLE_ERR_UNK_CONN_ID Unknown Connection Identifier 0x0203 0x03 BLE_ERR_HW_FAIL Hardware Failure 0x0204 0x04 BLE_ERR_PAGE_TMO Page Timeout 0x0205 0x05 BLE_ERR_AUTH_FAIL Authentication Failure 0x0206 0x06 BLE_ERR_PINKEY_MISSING PIN or Key Missing 0x0207 0x07 BLE_ERR_MEM_CAPACITY Memory Capacity Exceeded 0x0208 0x08 BLE_ERR_CONN_SPVN_TMO Connection Timeout 0x0209 0x09 BLE_ERR_CONN_LIMIT Connection Limit Exceeded 0x020a 0x0a BLE_ERR_SYNCH_CONN_LIMIT Synchronous Connection Limit To A Device Exceeded 0x020b 0x0b BLE_ERR_ACL_CONN_EXISTS ACL Connection Already Exists 0x020c 0x0c BLE_ERR_CMD_DISALLOWED Command Disallowed 0x020d 0x0d BLE_ERR_CONN_REJ_RESOURCES Connection Rejected due to Limited Resources 0x020e 0x0e BLE_ERR_CONN_REJ_SECURITY Connection Rejected Due To Security Reasons 0x020f 0x0f BLE_ERR_CONN_REJ_BD_ADDR Connection Rejected due to Unacceptable BD_ADDR 0x0210 0x10 BLE_ERR_CONN_ACCEPT_TMO Connection Accept Timeout Exceeded 0x0211 0x11 BLE_ERR_UNSUPPORTED Unsupported Feature or Parameter Value 0x0212 0x12 BLE_ERR_INV_HCI_CMD_PARMS Invalid HCI Command Parameters 0x0213 0x13 BLE_ERR_REM_USER_CONN_TERM Remote User Terminated Connection 0x0214 0x14 BLE_ERR_RD_CONN_TERM_RESRCS Remote Device Terminated Connection due to Low Resources 0x0215 0x15 BLE_ERR_RD_CONN_TERM_PWROFF Remote Device Terminated Connection due to Power Off 0x0216 0x16 BLE_ERR_CONN_TERM_LOCAL Connection Terminated By Local Host 0x0217 0x17 BLE_ERR_REPEATED_ATTEMPTS Repeated Attempts 0x0218 0x18 BLE_ERR_NO_PAIRING Pairing Not Allowed 0x0219 0x19 BLE_ERR_UNK_LMP Unknown LMP PDU 0x021a 0x1a BLE_ERR_UNSUPP_REM_FEATURE Unsupported Remote Feature / Unsupported LMP Feature 0x021b 0x1b BLE_ERR_SCO_OFFSET SCO Offset Rejected 0x021c 0x1c BLE_ERR_SCO_ITVL SCO Interval Rejected 0x021d 0x1d BLE_ERR_SCO_AIR_MODE SCO Air Mode Rejected 0x021e 0x1e BLE_ERR_INV_LMP_LL_PARM Invalid LMP Parameters / Invalid LL Parameters 0x021f 0x1f BLE_ERR_UNSPECIFIED Unspecified Error 0x0220 0x20 BLE_ERR_UNSUPP_LMP_LL_PARM Unsupported LMP Parameter Value / Unsupported LL Parameter Value 0x0221 0x21 BLE_ERR_NO_ROLE_CHANGE Role Change Not Allowed 0x0222 0x22 BLE_ERR_LMP_LL_RSP_TMO LMP Response Timeout / LL Response Timeout 0x0223 0x23 BLE_ERR_LMP_COLLISION LMP Error Transaction Collision 0x0224 0x24 BLE_ERR_LMP_PDU LMP PDU Not Allowed 0x0225 0x25 BLE_ERR_ENCRYPTION_MODE Encryption Mode Not Acceptable 0x0226 0x26 BLE_ERR_LINK_KEY_CHANGE Link Key cannot be Changed 0x0227 0x27 BLE_ERR_UNSUPP_QOS Requested QoS Not Supported 0x0228 0x28 BLE_ERR_INSTANT_PASSED Instant Passed 0x0229 0x29 BLE_ERR_UNIT_KEY_PAIRING Pairing With Unit Key Not Supported 0x022a 0x2a BLE_ERR_DIFF_TRANS_COLL Different Transaction Collision 0x022c 0x2c BLE_ERR_QOS_PARM QoS Unacceptable Parameter 0x022d 0x2d BLE_ERR_QOS_REJECTED QoS Rejected 0x022e 0x2e BLE_ERR_CHAN_CLASS Channel Classification Not Supported 0x022f 0x2f BLE_ERR_INSUFFICIENT_SEC Insufficient Security 0x0230 0x30 BLE_ERR_PARM_OUT_OF_RANGE Parameter Out Of Mandatory Range 0x0232 0x32 BLE_ERR_PENDING_ROLE_SW Role Switch Pending 0x0234 0x34 BLE_ERR_RESERVED_SLOT Reserved Slot Violation 0x0235 0x35 BLE_ERR_ROLE_SW_FAIL Role Switch Failed 0x0236 0x36 BLE_ERR_INQ_RSP_TOO_BIG Extended Inquiry Response Too Large 0x0237 0x37 BLE_ERR_SEC_SIMPLE_PAIR Secure Simple Pairing Not Supported By Host 0x0238 0x38 BLE_ERR_HOST_BUSY_PAIR Host Busy - Pairing 0x0239 0x39 BLE_ERR_CONN_REJ_CHANNEL Connection Rejected due to No Suitable Channel Found 0x023a 0x3a BLE_ERR_CTLR_BUSY Controller Busy 0x023b 0x3b BLE_ERR_CONN_PARMS Unacceptable Connection Parameters 0x023c 0x3c BLE_ERR_DIR_ADV_TMO Directed Advertising Timeout 0x023d 0x3d BLE_ERR_CONN_TERM_MIC Connection Terminated due to MIC Failure 0x023e 0x3e BLE_ERR_CONN_ESTABLISHMENT Connection Failed to be Established 0x023f 0x3f BLE_ERR_MAC_CONN_FAIL MAC Connection Failed 0x0240 0x40 BLE_ERR_COARSE_CLK_ADJ Coarse Clock Adjustment Rejected but Will Try to Adjust Using Clock Dragging","title":"Return codes - HCI"},{"location":"network/ble/ble_hs/ble_hs_return_codes/#return-codes-l2cap","text":"NimBLE Value Formal Value Name Condition 0x0300 0x00 BLE_L2CAP_SIG_ERR_CMD_NOT_UNDERSTOOD Invalid or unsupported incoming L2CAP sig command. 0x0301 0x01 BLE_L2CAP_SIG_ERR_MTU_EXCEEDED Incoming packet too large. 0x0302 0x02 BLE_L2CAP_SIG_ERR_INVALID_CID No channel with specified ID.","title":"Return codes - L2CAP"},{"location":"network/ble/ble_hs/ble_hs_return_codes/#return-codes-security-manager-us","text":"NimBLE Value Formal Value Name Condition 0x0401 0x01 BLE_SM_ERR_PASSKEY The user input of passkey failed, for example, the user cancelled the operation. 0x0402 0x02 BLE_SM_ERR_OOB The OOB data is not available. 0x0403 0x03 BLE_SM_ERR_AUTHREQ The pairing procedure cannot be performed as authentication requirements cannot be met due to IO capabilities of one or both devices. 0x0404 0x04 BLE_SM_ERR_CONFIRM_MISMATCH The confirm value does not match the calculated compare value. 0x0405 0x05 BLE_SM_ERR_PAIR_NOT_SUPP Pairing is not supported by the device. 0x0406 0x06 BLE_SM_ERR_ENC_KEY_SZ The resultant encryption key size is insufficient for the security requirements of this device. 0x0407 0x07 BLE_SM_ERR_CMD_NOT_SUPP The SMP command received is not supported on this device. 0x0408 0x08 BLE_SM_ERR_UNSPECIFIED Pairing failed due to an unspecified reason. 0x0409 0x09 BLE_SM_ERR_REPEATED Pairing or authentication procedure is disallowed because too little time has elapsed since last pairing request or security request. 0x040a 0x0a BLE_SM_ERR_INVAL The Invalid Parameters error code indicates that the command length is invalid or that a parameter is outside of the specified range. 0x040b 0x0b BLE_SM_ERR_DHKEY Indicates to the remote device that the DHKey Check value received doesn\u2019t match the one calculated by the local device. 0x040c 0x0c BLE_SM_ERR_NUMCMP Indicates that the confirm values in the numeric comparison protocol do not match. 0x040d 0x0d BLE_SM_ERR_ALREADY Indicates that the pairing over the LE transport failed due to a Pairing Request sent over the BR/EDR transport in process. 0x040e 0x0e BLE_SM_ERR_CROSS_TRANS Indicates that the BR/EDR Link Key generated on the BR/EDR transport cannot be used to derive and distribute keys for the LE transport.","title":"Return codes - Security manager (us)"},{"location":"network/ble/ble_hs/ble_hs_return_codes/#return-codes-security-manager-peer","text":"NimBLE Value Formal Value Name Condition 0x0501 0x01 BLE_SM_ERR_PASSKEY The user input of passkey failed, for example, the user cancelled the operation. 0x0502 0x02 BLE_SM_ERR_OOB The OOB data is not available. 0x0503 0x03 BLE_SM_ERR_AUTHREQ The pairing procedure cannot be performed as authentication requirements cannot be met due to IO capabilities of one or both devices. 0x0504 0x04 BLE_SM_ERR_CONFIRM_MISMATCH The confirm value does not match the calculated compare value. 0x0505 0x05 BLE_SM_ERR_PAIR_NOT_SUPP Pairing is not supported by the device. 0x0506 0x06 BLE_SM_ERR_ENC_KEY_SZ The resultant encryption key size is insufficient for the security requirements of this device. 0x0507 0x07 BLE_SM_ERR_CMD_NOT_SUPP The SMP command received is not supported on this device. 0x0508 0x08 BLE_SM_ERR_UNSPECIFIED Pairing failed due to an unspecified reason. 0x0509 0x09 BLE_SM_ERR_REPEATED Pairing or authentication procedure is disallowed because too little time has elapsed since last pairing request or security request. 0x050a 0x0a BLE_SM_ERR_INVAL The Invalid Parameters error code indicates that the command length is invalid or that a parameter is outside of the specified range. 0x050b 0x0b BLE_SM_ERR_DHKEY Indicates to the remote device that the DHKey Check value received doesn\u2019t match the one calculated by the local device. 0x050c 0x0c BLE_SM_ERR_NUMCMP Indicates that the confirm values in the numeric comparison protocol do not match. 0x050d 0x0d BLE_SM_ERR_ALREADY Indicates that the pairing over the LE transport failed due to a Pairing Request sent over the BR/EDR transport in process. 0x050e 0x0e BLE_SM_ERR_CROSS_TRANS Indicates that the BR/EDR Link Key generated on the BR/EDR transport cannot be used to derive and distribute keys for the LE transport.","title":"Return codes - Security manager (peer)"},{"location":"network/ble/ble_hs/ble_att/ble_att/","text":"NimBLE Host ATT Client Reference Introduction The Attribute Protocol (ATT) is a mid-level protocol that all BLE devices use to exchange data. Data is exchanged when an ATT client reads or writes an attribute belonging to an ATT server. Any device that needs to send or receive data must support both the client and server functionality of the ATT protocol. The only devices which do not support ATT are the most basic ones: broadcasters and observers (i.e., beaconing devices and listening devices). Most ATT functionality is not interesting to an application. Rather than use ATT directly, an application uses the higher level GATT profile, which sits directly above ATT in the host. NimBLE exposes the few bits of ATT functionality which are not encompassed by higher level GATT functions. This section documents the ATT functionality that the NimBLE host exposes to the application. Header #include \"host/ble_hs.h\" Definitions None. Function Description ble_att_mtu Retrieves the ATT MTU of the specified connection. ble_att_set_preferred_mtu Sets the preferred ATT MTU; the device will indicate this value in all subseqeunt ATT MTU exchanges. ble_att_svr_read_local Reads a locally registered attribute. ble_att_svr_write_local Writes a locally registered attribute.","title":"toc"},{"location":"network/ble/ble_hs/ble_att/ble_att/#nimble-host-att-client-reference","text":"","title":"NimBLE Host ATT Client Reference"},{"location":"network/ble/ble_hs/ble_att/ble_att/#introduction","text":"The Attribute Protocol (ATT) is a mid-level protocol that all BLE devices use to exchange data. Data is exchanged when an ATT client reads or writes an attribute belonging to an ATT server. Any device that needs to send or receive data must support both the client and server functionality of the ATT protocol. The only devices which do not support ATT are the most basic ones: broadcasters and observers (i.e., beaconing devices and listening devices). Most ATT functionality is not interesting to an application. Rather than use ATT directly, an application uses the higher level GATT profile, which sits directly above ATT in the host. NimBLE exposes the few bits of ATT functionality which are not encompassed by higher level GATT functions. This section documents the ATT functionality that the NimBLE host exposes to the application.","title":"Introduction"},{"location":"network/ble/ble_hs/ble_att/ble_att/#header","text":"#include \"host/ble_hs.h\"","title":"Header"},{"location":"network/ble/ble_hs/ble_att/ble_att/#definitions","text":"None. Function Description ble_att_mtu Retrieves the ATT MTU of the specified connection. ble_att_set_preferred_mtu Sets the preferred ATT MTU; the device will indicate this value in all subseqeunt ATT MTU exchanges. ble_att_svr_read_local Reads a locally registered attribute. ble_att_svr_write_local Writes a locally registered attribute.","title":"Definitions"},{"location":"network/ble/ble_hs/ble_att/functions/ble_att_mtu/","text":"ble_att_mtu uint16_t ble_att_mtu ( uint16_t conn_handle ) Description Retrieves the ATT MTU of the specified connection. If an MTU exchange for this connection has occurred, the MTU is the lower of the two peers' preferred values. Otherwise, the MTU is the default value of 23. Parameters Parameter Description conn_handle The handle of the connection to query. Returned values The specified connection's ATT MTU.","title":"ble_att_mtu"},{"location":"network/ble/ble_hs/ble_att/functions/ble_att_mtu/#ble_att_mtu","text":"uint16_t ble_att_mtu ( uint16_t conn_handle )","title":"ble_att_mtu"},{"location":"network/ble/ble_hs/ble_att/functions/ble_att_mtu/#description","text":"Retrieves the ATT MTU of the specified connection. If an MTU exchange for this connection has occurred, the MTU is the lower of the two peers' preferred values. Otherwise, the MTU is the default value of 23.","title":"Description"},{"location":"network/ble/ble_hs/ble_att/functions/ble_att_mtu/#parameters","text":"Parameter Description conn_handle The handle of the connection to query.","title":"Parameters"},{"location":"network/ble/ble_hs/ble_att/functions/ble_att_mtu/#returned-values","text":"The specified connection's ATT MTU.","title":"Returned values"},{"location":"network/ble/ble_hs/ble_att/functions/ble_att_set_preferred_mtu/","text":"ble_att_set_preferred_mtu int ble_att_set_preferred_mtu ( uint16_t mtu ) Description Sets the preferred ATT MTU; the device will indicate this value in all subseqeunt ATT MTU exchanges. The ATT MTU of a connection is equal to the lower of the two peers' preferred MTU values. The ATT MTU is what dictates the maximum size of any message sent during a GATT procedure. The specified MTU must be within the following range: [23, BLE_ATT_MTU_MAX]. 23 is a minimum imposed by the Bluetooth specification; BLE_ATT_MTU_MAX is a NimBLE compile-time setting. Parameters Parameter Description mtu The preferred ATT MTU. Returned values Value Condition 0 Success. BLE_HS_EINVAL The specifeid value is not within the allowed range.","title":"ble_att_set_preferred_mtu"},{"location":"network/ble/ble_hs/ble_att/functions/ble_att_set_preferred_mtu/#ble_att_set_preferred_mtu","text":"int ble_att_set_preferred_mtu ( uint16_t mtu )","title":"ble_att_set_preferred_mtu"},{"location":"network/ble/ble_hs/ble_att/functions/ble_att_set_preferred_mtu/#description","text":"Sets the preferred ATT MTU; the device will indicate this value in all subseqeunt ATT MTU exchanges. The ATT MTU of a connection is equal to the lower of the two peers' preferred MTU values. The ATT MTU is what dictates the maximum size of any message sent during a GATT procedure. The specified MTU must be within the following range: [23, BLE_ATT_MTU_MAX]. 23 is a minimum imposed by the Bluetooth specification; BLE_ATT_MTU_MAX is a NimBLE compile-time setting.","title":"Description"},{"location":"network/ble/ble_hs/ble_att/functions/ble_att_set_preferred_mtu/#parameters","text":"Parameter Description mtu The preferred ATT MTU.","title":"Parameters"},{"location":"network/ble/ble_hs/ble_att/functions/ble_att_set_preferred_mtu/#returned-values","text":"Value Condition 0 Success. BLE_HS_EINVAL The specifeid value is not within the allowed range.","title":"Returned values"},{"location":"network/ble/ble_hs/ble_att/functions/ble_att_svr_read_local/","text":"ble_att_svr_read_local int ble_att_svr_read_local ( uint16_t attr_handle , struct os_mbuf **out_om ) Description Reads a locally registered attribute. If the specified attribute handle coresponds to a GATT characteristic value or descriptor, the read is performed by calling the registered GATT access callback. Parameters Parameter Description attr_handle The 16-bit handle of the attribute to read. out_om On success, this is made to point to a newly-allocated mbuf containing the attribute data read. Returned values Value Condition 0 Success. ATT return code The attribute access callback reports failure. Core return code Unexpected error.","title":"ble_att_svr_read_local"},{"location":"network/ble/ble_hs/ble_att/functions/ble_att_svr_read_local/#ble_att_svr_read_local","text":"int ble_att_svr_read_local ( uint16_t attr_handle , struct os_mbuf **out_om )","title":"ble_att_svr_read_local"},{"location":"network/ble/ble_hs/ble_att/functions/ble_att_svr_read_local/#description","text":"Reads a locally registered attribute. If the specified attribute handle coresponds to a GATT characteristic value or descriptor, the read is performed by calling the registered GATT access callback.","title":"Description"},{"location":"network/ble/ble_hs/ble_att/functions/ble_att_svr_read_local/#parameters","text":"Parameter Description attr_handle The 16-bit handle of the attribute to read. out_om On success, this is made to point to a newly-allocated mbuf containing the attribute data read.","title":"Parameters"},{"location":"network/ble/ble_hs/ble_att/functions/ble_att_svr_read_local/#returned-values","text":"Value Condition 0 Success. ATT return code The attribute access callback reports failure. Core return code Unexpected error.","title":"Returned values"},{"location":"network/ble/ble_hs/ble_att/functions/ble_att_svr_write_local/","text":"ble_att_svr_write_local int ble_att_svr_write_local ( uint16_t attr_handle , struct os_mbuf *om ) Description Writes a locally registered attribute. This function consumes the supplied mbuf regardless of the outcome. If the specified attribute handle coresponds to a GATT characteristic value or descriptor, the write is performed by calling the registered GATT access callback. Parameters Parameter Description attr_handle The 16-bit handle of the attribute to write. om The value to write to the attribute. Returned values Value Condition 0 Success. ATT return code The attribute access callback reports failure. Core return code Unexpected error.","title":"ble_att_svr_write_local"},{"location":"network/ble/ble_hs/ble_att/functions/ble_att_svr_write_local/#ble_att_svr_write_local","text":"int ble_att_svr_write_local ( uint16_t attr_handle , struct os_mbuf *om )","title":"ble_att_svr_write_local"},{"location":"network/ble/ble_hs/ble_att/functions/ble_att_svr_write_local/#description","text":"Writes a locally registered attribute. This function consumes the supplied mbuf regardless of the outcome. If the specified attribute handle coresponds to a GATT characteristic value or descriptor, the write is performed by calling the registered GATT access callback.","title":"Description"},{"location":"network/ble/ble_hs/ble_att/functions/ble_att_svr_write_local/#parameters","text":"Parameter Description attr_handle The 16-bit handle of the attribute to write. om The value to write to the attribute.","title":"Parameters"},{"location":"network/ble/ble_hs/ble_att/functions/ble_att_svr_write_local/#returned-values","text":"Value Condition 0 Success. ATT return code The attribute access callback reports failure. Core return code Unexpected error.","title":"Returned values"},{"location":"network/ble/ble_hs/ble_gap/ble_gap/","text":"NimBLE Host GAP Reference Introduction The Generic Access Profile (GAP) is responsible for all connecting, advertising, scanning, and connection updating operations. Header #include \"host/ble_hs.h\" Definitions BLE host GAP definitions Functions Function Description ble_gap_adv_active Indicates whether an advertisement procedure is currently in progress. ble_gap_adv_rsp_set_fields Configures the data to include in subsequent scan responses. ble_gap_adv_set_fields Configures the data to include in subsequent advertisements. ble_gap_adv_start Initiates advertising. ble_gap_adv_stop Stops the currently-active advertising procedure. ble_gap_conn_active Indicates whether a connect procedure is currently in progress. ble_gap_conn_cancel Aborts a connect procedure in progress. ble_gap_conn_find Searches for a connection with the specified handle. ble_gap_conn_rssi Retrieves the most-recently measured RSSI for the specified connection. ble_gap_connect Initiates a connect procedure. ble_gap_disc Performs the Limited or General Discovery Procedures. ble_gap_disc_active Indicates whether a discovery procedure is currently in progress. ble_gap_disc_cancel Cancels the discovery procedure currently in progress. ble_gap_security_initiate Initiates the GAP encryption procedure. ble_gap_terminate Terminates an established connection. ble_gap_update_params Initiates a connection parameter update procedure. ble_gap_wl_set Overwrites the controller's white list with the specified contents.","title":"toc"},{"location":"network/ble/ble_hs/ble_gap/ble_gap/#nimble-host-gap-reference","text":"","title":"NimBLE Host GAP Reference"},{"location":"network/ble/ble_hs/ble_gap/ble_gap/#introduction","text":"The Generic Access Profile (GAP) is responsible for all connecting, advertising, scanning, and connection updating operations.","title":"Introduction"},{"location":"network/ble/ble_hs/ble_gap/ble_gap/#header","text":"#include \"host/ble_hs.h\"","title":"Header"},{"location":"network/ble/ble_hs/ble_gap/ble_gap/#definitions","text":"BLE host GAP definitions","title":"Definitions"},{"location":"network/ble/ble_hs/ble_gap/ble_gap/#functions","text":"Function Description ble_gap_adv_active Indicates whether an advertisement procedure is currently in progress. ble_gap_adv_rsp_set_fields Configures the data to include in subsequent scan responses. ble_gap_adv_set_fields Configures the data to include in subsequent advertisements. ble_gap_adv_start Initiates advertising. ble_gap_adv_stop Stops the currently-active advertising procedure. ble_gap_conn_active Indicates whether a connect procedure is currently in progress. ble_gap_conn_cancel Aborts a connect procedure in progress. ble_gap_conn_find Searches for a connection with the specified handle. ble_gap_conn_rssi Retrieves the most-recently measured RSSI for the specified connection. ble_gap_connect Initiates a connect procedure. ble_gap_disc Performs the Limited or General Discovery Procedures. ble_gap_disc_active Indicates whether a discovery procedure is currently in progress. ble_gap_disc_cancel Cancels the discovery procedure currently in progress. ble_gap_security_initiate Initiates the GAP encryption procedure. ble_gap_terminate Terminates an established connection. ble_gap_update_params Initiates a connection parameter update procedure. ble_gap_wl_set Overwrites the controller's white list with the specified contents.","title":"Functions"},{"location":"network/ble/ble_hs/ble_gap/definitions/ble_gap_defs/","text":"GAP events typedef int ble_gap_event_fn ( struct ble_gap_event *ctxt , void *arg ); #define BLE_GAP_EVENT_CONNECT 0 #define BLE_GAP_EVENT_DISCONNECT 1 #define BLE_GAP_EVENT_CONN_CANCEL 2 #define BLE_GAP_EVENT_CONN_UPDATE 3 #define BLE_GAP_EVENT_CONN_UPDATE_REQ 4 #define BLE_GAP_EVENT_L2CAP_UPDATE_REQ 5 #define BLE_GAP_EVENT_TERM_FAILURE 6 #define BLE_GAP_EVENT_DISC 7 #define BLE_GAP_EVENT_DISC_COMPLETE 8 #define BLE_GAP_EVENT_ADV_COMPLETE 9 #define BLE_GAP_EVENT_ENC_CHANGE 10 #define BLE_GAP_EVENT_PASSKEY_ACTION 11 #define BLE_GAP_EVENT_NOTIFY_RX 12 #define BLE_GAP_EVENT_NOTIFY_TX 13 #define BLE_GAP_EVENT_SUBSCRIBE 14 /** * Represents a GAP-related event. When such an event occurs, the host * notifies the application by passing an instance of this structure to an * application-specified callback. */ struct ble_gap_event { /** * Indicates the type of GAP event that occurred. This is one of the * BLE_GAP_EVENT codes. */ uint8_t type ; /** * A discriminated union containing additional details concerning the GAP * event. The 'type' field indicates which member of the union is valid. */ union { /** * Represents a connection attempt. Valid for the following event * types: * o BLE_GAP_EVENT_CONNECT */ struct { /** * The status of the connection attempt; * o 0: the connection was successfully established. * o BLE host error code: the connection attempt failed for * the specified reason. */ int status ; /** The handle of the relevant connection. */ uint16_t conn_handle ; } connect ; /** * Represents a terminated connection. Valid for the following event * types: * o BLE_GAP_EVENT_DISCONNECT */ struct { /** * A BLE host return code indicating the reason for the * disconnect. */ int reason ; /** Information about the connection prior to termination. */ struct ble_gap_conn_desc conn ; } disconnect ; /** * Represents an advertising report received during a discovery * procedure. Valid for the following event types: * o BLE_GAP_EVENT_DISC */ struct ble_gap_disc_desc disc ; /** * Represents an attempt to update a connection's parameters. If the * attempt was successful, the connection's descriptor reflects the * updated parameters. * * Valid for the following event types: * o BLE_GAP_EVENT_CONN_UPDATE */ struct { /** * The result of the connection update attempt; * o 0: the connection was successfully updated. * o BLE host error code: the connection update attempt failed * for the specified reason. */ int status ; /** The handle of the relevant connection. */ uint16_t conn_handle ; } conn_update ; /** * Represents a peer's request to update the connection parameters. * This event is generated when a peer performs any of the following * procedures: * o L2CAP Connection Parameter Update Procedure * o Link-Layer Connection Parameters Request Procedure * * To reject the request, return a non-zero HCI error code. The value * returned is the reject reason given to the controller. * * Valid for the following event types: * o BLE_GAP_EVENT_L2CAP_UPDATE_REQ * o BLE_GAP_EVENT_CONN_UPDATE_REQ */ struct { /** * Indicates the connection parameters that the peer would like to * use. */ const struct ble_gap_upd_params *peer_params ; /** * Indicates the connection parameters that the local device would * like to use. The application callback should fill this in. By * default, this struct contains the requested parameters (i.e., * it is a copy of 'peer_params'). */ struct ble_gap_upd_params *self_params ; /** The handle of the relevant connection. */ uint16_t conn_handle ; } conn_update_req ; /** * Represents a failed attempt to terminate an established connection. * Valid for the following event types: * o BLE_GAP_EVENT_TERM_FAILURE */ struct { /** * A BLE host return code indicating the reason for the failure. */ int status ; /** The handle of the relevant connection. */ uint16_t conn_handle ; } term_failure ; /** * Represents an attempt to change the encrypted state of a * connection. If the attempt was successful, the connection * descriptor reflects the updated encrypted state. * * Valid for the following event types: * o BLE_GAP_EVENT_ENC_CHANGE */ struct { /** * Indicates the result of the encryption state change attempt; * o 0: the encrypted state was successfully updated; * o BLE host error code: the encryption state change attempt * failed for the specified reason. */ int status ; /** The handle of the relevant connection. */ uint16_t conn_handle ; } enc_change ; /** * Represents a passkey query needed to complete a pairing procedure. * * Valid for the following event types: * o BLE_GAP_EVENT_PASSKEY_ACTION */ struct { /** Contains details about the passkey query. */ struct ble_gap_passkey_params params ; /** The handle of the relevant connection. */ uint16_t conn_handle ; } passkey ; /** * Represents a received ATT notification or indication. * * Valid for the following event types: * o BLE_GAP_EVENT_NOTIFY_RX */ struct { /** * The contents of the notification or indication. If the * application wishes to retain this mbuf for later use, it must * set this pointer to NULL to prevent the stack from freeing it. */ struct os_mbuf *om ; /** The handle of the relevant ATT attribute. */ uint16_t attr_handle ; /** The handle of the relevant connection. */ uint16_t conn_handle ; /** * Whether the received command is a notification or an * indication; * o 0: Notification; * o 1: Indication. */ uint8_t indication: 1 ; } notify_rx ; /** * Represents a transmitted ATT notification or indication, or a * completed indication transaction. * * Valid for the following event types: * o BLE_GAP_EVENT_NOTIFY_TX */ struct { /** * The status of the notification or indication transaction; * o 0: Command successfully sent; * o BLE_HS_EDONE: Confirmation (indication ack) received; * o BLE_HS_ETIMEOUT: Confirmation (indication ack) never * received; * o Other return code: Error. */ int status ; /** The handle of the relevant connection. */ uint16_t conn_handle ; /** The handle of the relevant characterstic value. */ uint16_t attr_handle ; /** * Whether the transmitted command is a notification or an * indication; * o 0: Notification; * o 1: Indication. */ uint8_t indication: 1 ; } notify_tx ; /** * Represents a state change in a peer's subscription status. In this * comment, the term \"update\" is used to refer to either a notification * or an indication. This event is triggered by any of the following * occurrences: * o Peer enables or disables updates via a CCCD write. * o Connection is about to be terminated and the peer is * subscribed to updates. * o Peer is now subscribed to updates after its state was restored * from persistence. This happens when bonding is restored. * * Valid for the following event types: * o BLE_GAP_EVENT_SUBSCRIBE */ struct { /** The handle of the relevant connection. */ uint16_t conn_handle ; /** The value handle of the relevant characteristic. */ uint16_t attr_handle ; /** One of the BLE_GAP_SUBSCRIBE_REASON codes. */ uint8_t reason ; /** Whether the peer was previously subscribed to notifications. */ uint8_t prev_notify: 1 ; /** Whether the peer is currently subscribed to notifications. */ uint8_t cur_notify: 1 ; /** Whether the peer was previously subscribed to indications. */ uint8_t prev_indicate: 1 ; /** Whether the peer is currently subscribed to indications. */ uint8_t cur_indicate: 1 ; } subscribe ; }; }; #define BLE_GAP_CONN_MODE_NON 0 #define BLE_GAP_CONN_MODE_DIR 1 #define BLE_GAP_CONN_MODE_UND 2 #define BLE_GAP_DISC_MODE_NON 0 #define BLE_GAP_DISC_MODE_LTD 1 #define BLE_GAP_DISC_MODE_GEN 2 struct ble_gap_white_entry { uint8_t addr_type ; uint8_t addr [ 6 ]; }; /*** Reason codes for the subscribe GAP event. */ /** Peer's CCCD subscription state changed due to a descriptor write. */ #define BLE_GAP_SUBSCRIBE_REASON_WRITE 1 /** Peer's CCCD subscription state cleared due to connection termination. */ #define BLE_GAP_SUBSCRIBE_REASON_TERM 2 /** * Peer's CCCD subscription state changed due to restore from persistence * (bonding restored). */ #define BLE_GAP_SUBSCRIBE_REASON_RESTORE 3 struct ble_gap_sec_state { unsigned encrypted: 1 ; unsigned authenticated: 1 ; unsigned bonded: 1 ; }; /** * @param discoverable_mode One of the following constants: * o BLE_GAP_DISC_MODE_NON * (non-discoverable; 3.C.9.2.2). * o BLE_GAP_DISC_MODE_LTD * (limited-discoverable; 3.C.9.2.3). * o BLE_GAP_DISC_MODE_GEN * (general-discoverable; 3.C.9.2.4). * @param connectable_mode One of the following constants: * o BLE_GAP_CONN_MODE_NON * (non-connectable; 3.C.9.3.2). * o BLE_GAP_CONN_MODE_DIR * (directed-connectable; 3.C.9.3.3). * o BLE_GAP_CONN_MODE_UND * (undirected-connectable; 3.C.9.3.4). */ struct ble_gap_adv_params { /*** Mandatory fields. */ uint8_t conn_mode ; uint8_t disc_mode ; /*** Optional fields; assign 0 to make the stack calculate them. */ uint16_t itvl_min ; uint16_t itvl_max ; uint8_t channel_map ; uint8_t filter_policy ; uint8_t high_duty_cycle: 1 ; }; #define BLE_GAP_ROLE_MASTER 0 #define BLE_GAP_ROLE_SLAVE 1 struct ble_gap_conn_desc { struct ble_gap_sec_state sec_state ; uint8_t peer_ota_addr [ 6 ]; uint8_t peer_id_addr [ 6 ]; uint8_t our_id_addr [ 6 ]; uint8_t our_ota_addr [ 6 ]; uint16_t conn_handle ; uint16_t conn_itvl ; uint16_t conn_latency ; uint16_t supervision_timeout ; uint8_t peer_ota_addr_type ; uint8_t peer_id_addr_type ; uint8_t our_id_addr_type ; uint8_t our_ota_addr_type ; uint8_t role ; uint8_t master_clock_accuracy ; }; struct ble_gap_conn_params { uint16_t scan_itvl ; uint16_t scan_window ; uint16_t itvl_min ; uint16_t itvl_max ; uint16_t latency ; uint16_t supervision_timeout ; uint16_t min_ce_len ; uint16_t max_ce_len ; }; struct ble_gap_disc_params { uint16_t itvl ; uint16_t window ; uint8_t filter_policy ; uint8_t limited: 1 ; uint8_t passive: 1 ; uint8_t filter_duplicates: 1 ; }; struct ble_gap_upd_params { uint16_t itvl_min ; uint16_t itvl_max ; uint16_t latency ; uint16_t supervision_timeout ; uint16_t min_ce_len ; uint16_t max_ce_len ; }; struct ble_gap_passkey_params { uint8_t action ; uint32_t numcmp ; }; struct ble_gap_disc_desc { /*** Common fields. */ uint8_t event_type ; uint8_t addr_type ; uint8_t length_data ; int8_t rssi ; uint8_t addr [ 6 ]; /*** LE advertising report fields; both null if no data present. */ uint8_t *data ; struct ble_hs_adv_fields *fields ; /*** * LE direct advertising report fields; direct_addr_type is * BLE_GAP_ADDR_TYPE_NONE if direct address fields are not present. */ uint8_t direct_addr_type ; uint8_t direct_addr [ 6 ]; };","title":"GAP definitions"},{"location":"network/ble/ble_hs/ble_gap/definitions/ble_gap_defs/#gap-events","text":"typedef int ble_gap_event_fn ( struct ble_gap_event *ctxt , void *arg ); #define BLE_GAP_EVENT_CONNECT 0 #define BLE_GAP_EVENT_DISCONNECT 1 #define BLE_GAP_EVENT_CONN_CANCEL 2 #define BLE_GAP_EVENT_CONN_UPDATE 3 #define BLE_GAP_EVENT_CONN_UPDATE_REQ 4 #define BLE_GAP_EVENT_L2CAP_UPDATE_REQ 5 #define BLE_GAP_EVENT_TERM_FAILURE 6 #define BLE_GAP_EVENT_DISC 7 #define BLE_GAP_EVENT_DISC_COMPLETE 8 #define BLE_GAP_EVENT_ADV_COMPLETE 9 #define BLE_GAP_EVENT_ENC_CHANGE 10 #define BLE_GAP_EVENT_PASSKEY_ACTION 11 #define BLE_GAP_EVENT_NOTIFY_RX 12 #define BLE_GAP_EVENT_NOTIFY_TX 13 #define BLE_GAP_EVENT_SUBSCRIBE 14 /** * Represents a GAP-related event. When such an event occurs, the host * notifies the application by passing an instance of this structure to an * application-specified callback. */ struct ble_gap_event { /** * Indicates the type of GAP event that occurred. This is one of the * BLE_GAP_EVENT codes. */ uint8_t type ; /** * A discriminated union containing additional details concerning the GAP * event. The 'type' field indicates which member of the union is valid. */ union { /** * Represents a connection attempt. Valid for the following event * types: * o BLE_GAP_EVENT_CONNECT */ struct { /** * The status of the connection attempt; * o 0: the connection was successfully established. * o BLE host error code: the connection attempt failed for * the specified reason. */ int status ; /** The handle of the relevant connection. */ uint16_t conn_handle ; } connect ; /** * Represents a terminated connection. Valid for the following event * types: * o BLE_GAP_EVENT_DISCONNECT */ struct { /** * A BLE host return code indicating the reason for the * disconnect. */ int reason ; /** Information about the connection prior to termination. */ struct ble_gap_conn_desc conn ; } disconnect ; /** * Represents an advertising report received during a discovery * procedure. Valid for the following event types: * o BLE_GAP_EVENT_DISC */ struct ble_gap_disc_desc disc ; /** * Represents an attempt to update a connection's parameters. If the * attempt was successful, the connection's descriptor reflects the * updated parameters. * * Valid for the following event types: * o BLE_GAP_EVENT_CONN_UPDATE */ struct { /** * The result of the connection update attempt; * o 0: the connection was successfully updated. * o BLE host error code: the connection update attempt failed * for the specified reason. */ int status ; /** The handle of the relevant connection. */ uint16_t conn_handle ; } conn_update ; /** * Represents a peer's request to update the connection parameters. * This event is generated when a peer performs any of the following * procedures: * o L2CAP Connection Parameter Update Procedure * o Link-Layer Connection Parameters Request Procedure * * To reject the request, return a non-zero HCI error code. The value * returned is the reject reason given to the controller. * * Valid for the following event types: * o BLE_GAP_EVENT_L2CAP_UPDATE_REQ * o BLE_GAP_EVENT_CONN_UPDATE_REQ */ struct { /** * Indicates the connection parameters that the peer would like to * use. */ const struct ble_gap_upd_params *peer_params ; /** * Indicates the connection parameters that the local device would * like to use. The application callback should fill this in. By * default, this struct contains the requested parameters (i.e., * it is a copy of 'peer_params'). */ struct ble_gap_upd_params *self_params ; /** The handle of the relevant connection. */ uint16_t conn_handle ; } conn_update_req ; /** * Represents a failed attempt to terminate an established connection. * Valid for the following event types: * o BLE_GAP_EVENT_TERM_FAILURE */ struct { /** * A BLE host return code indicating the reason for the failure. */ int status ; /** The handle of the relevant connection. */ uint16_t conn_handle ; } term_failure ; /** * Represents an attempt to change the encrypted state of a * connection. If the attempt was successful, the connection * descriptor reflects the updated encrypted state. * * Valid for the following event types: * o BLE_GAP_EVENT_ENC_CHANGE */ struct { /** * Indicates the result of the encryption state change attempt; * o 0: the encrypted state was successfully updated; * o BLE host error code: the encryption state change attempt * failed for the specified reason. */ int status ; /** The handle of the relevant connection. */ uint16_t conn_handle ; } enc_change ; /** * Represents a passkey query needed to complete a pairing procedure. * * Valid for the following event types: * o BLE_GAP_EVENT_PASSKEY_ACTION */ struct { /** Contains details about the passkey query. */ struct ble_gap_passkey_params params ; /** The handle of the relevant connection. */ uint16_t conn_handle ; } passkey ; /** * Represents a received ATT notification or indication. * * Valid for the following event types: * o BLE_GAP_EVENT_NOTIFY_RX */ struct { /** * The contents of the notification or indication. If the * application wishes to retain this mbuf for later use, it must * set this pointer to NULL to prevent the stack from freeing it. */ struct os_mbuf *om ; /** The handle of the relevant ATT attribute. */ uint16_t attr_handle ; /** The handle of the relevant connection. */ uint16_t conn_handle ; /** * Whether the received command is a notification or an * indication; * o 0: Notification; * o 1: Indication. */ uint8_t indication: 1 ; } notify_rx ; /** * Represents a transmitted ATT notification or indication, or a * completed indication transaction. * * Valid for the following event types: * o BLE_GAP_EVENT_NOTIFY_TX */ struct { /** * The status of the notification or indication transaction; * o 0: Command successfully sent; * o BLE_HS_EDONE: Confirmation (indication ack) received; * o BLE_HS_ETIMEOUT: Confirmation (indication ack) never * received; * o Other return code: Error. */ int status ; /** The handle of the relevant connection. */ uint16_t conn_handle ; /** The handle of the relevant characterstic value. */ uint16_t attr_handle ; /** * Whether the transmitted command is a notification or an * indication; * o 0: Notification; * o 1: Indication. */ uint8_t indication: 1 ; } notify_tx ; /** * Represents a state change in a peer's subscription status. In this * comment, the term \"update\" is used to refer to either a notification * or an indication. This event is triggered by any of the following * occurrences: * o Peer enables or disables updates via a CCCD write. * o Connection is about to be terminated and the peer is * subscribed to updates. * o Peer is now subscribed to updates after its state was restored * from persistence. This happens when bonding is restored. * * Valid for the following event types: * o BLE_GAP_EVENT_SUBSCRIBE */ struct { /** The handle of the relevant connection. */ uint16_t conn_handle ; /** The value handle of the relevant characteristic. */ uint16_t attr_handle ; /** One of the BLE_GAP_SUBSCRIBE_REASON codes. */ uint8_t reason ; /** Whether the peer was previously subscribed to notifications. */ uint8_t prev_notify: 1 ; /** Whether the peer is currently subscribed to notifications. */ uint8_t cur_notify: 1 ; /** Whether the peer was previously subscribed to indications. */ uint8_t prev_indicate: 1 ; /** Whether the peer is currently subscribed to indications. */ uint8_t cur_indicate: 1 ; } subscribe ; }; }; #define BLE_GAP_CONN_MODE_NON 0 #define BLE_GAP_CONN_MODE_DIR 1 #define BLE_GAP_CONN_MODE_UND 2 #define BLE_GAP_DISC_MODE_NON 0 #define BLE_GAP_DISC_MODE_LTD 1 #define BLE_GAP_DISC_MODE_GEN 2 struct ble_gap_white_entry { uint8_t addr_type ; uint8_t addr [ 6 ]; }; /*** Reason codes for the subscribe GAP event. */ /** Peer's CCCD subscription state changed due to a descriptor write. */ #define BLE_GAP_SUBSCRIBE_REASON_WRITE 1 /** Peer's CCCD subscription state cleared due to connection termination. */ #define BLE_GAP_SUBSCRIBE_REASON_TERM 2 /** * Peer's CCCD subscription state changed due to restore from persistence * (bonding restored). */ #define BLE_GAP_SUBSCRIBE_REASON_RESTORE 3 struct ble_gap_sec_state { unsigned encrypted: 1 ; unsigned authenticated: 1 ; unsigned bonded: 1 ; }; /** * @param discoverable_mode One of the following constants: * o BLE_GAP_DISC_MODE_NON * (non-discoverable; 3.C.9.2.2). * o BLE_GAP_DISC_MODE_LTD * (limited-discoverable; 3.C.9.2.3). * o BLE_GAP_DISC_MODE_GEN * (general-discoverable; 3.C.9.2.4). * @param connectable_mode One of the following constants: * o BLE_GAP_CONN_MODE_NON * (non-connectable; 3.C.9.3.2). * o BLE_GAP_CONN_MODE_DIR * (directed-connectable; 3.C.9.3.3). * o BLE_GAP_CONN_MODE_UND * (undirected-connectable; 3.C.9.3.4). */ struct ble_gap_adv_params { /*** Mandatory fields. */ uint8_t conn_mode ; uint8_t disc_mode ; /*** Optional fields; assign 0 to make the stack calculate them. */ uint16_t itvl_min ; uint16_t itvl_max ; uint8_t channel_map ; uint8_t filter_policy ; uint8_t high_duty_cycle: 1 ; }; #define BLE_GAP_ROLE_MASTER 0 #define BLE_GAP_ROLE_SLAVE 1 struct ble_gap_conn_desc { struct ble_gap_sec_state sec_state ; uint8_t peer_ota_addr [ 6 ]; uint8_t peer_id_addr [ 6 ]; uint8_t our_id_addr [ 6 ]; uint8_t our_ota_addr [ 6 ]; uint16_t conn_handle ; uint16_t conn_itvl ; uint16_t conn_latency ; uint16_t supervision_timeout ; uint8_t peer_ota_addr_type ; uint8_t peer_id_addr_type ; uint8_t our_id_addr_type ; uint8_t our_ota_addr_type ; uint8_t role ; uint8_t master_clock_accuracy ; }; struct ble_gap_conn_params { uint16_t scan_itvl ; uint16_t scan_window ; uint16_t itvl_min ; uint16_t itvl_max ; uint16_t latency ; uint16_t supervision_timeout ; uint16_t min_ce_len ; uint16_t max_ce_len ; }; struct ble_gap_disc_params { uint16_t itvl ; uint16_t window ; uint8_t filter_policy ; uint8_t limited: 1 ; uint8_t passive: 1 ; uint8_t filter_duplicates: 1 ; }; struct ble_gap_upd_params { uint16_t itvl_min ; uint16_t itvl_max ; uint16_t latency ; uint16_t supervision_timeout ; uint16_t min_ce_len ; uint16_t max_ce_len ; }; struct ble_gap_passkey_params { uint8_t action ; uint32_t numcmp ; }; struct ble_gap_disc_desc { /*** Common fields. */ uint8_t event_type ; uint8_t addr_type ; uint8_t length_data ; int8_t rssi ; uint8_t addr [ 6 ]; /*** LE advertising report fields; both null if no data present. */ uint8_t *data ; struct ble_hs_adv_fields *fields ; /*** * LE direct advertising report fields; direct_addr_type is * BLE_GAP_ADDR_TYPE_NONE if direct address fields are not present. */ uint8_t direct_addr_type ; uint8_t direct_addr [ 6 ]; };","title":"GAP events"},{"location":"network/ble/ble_hs/ble_gap/functions/ble_gap_adv_active/","text":"ble_gap_adv_active int ble_gap_adv_active ( void ) Description Indicates whether an advertisement procedure is currently in progress. Parameters None Returned values Value Condition 0 No advertisement procedure in progress. 1 Advertisement procedure in progress.","title":"ble_gap_adv_active"},{"location":"network/ble/ble_hs/ble_gap/functions/ble_gap_adv_active/#ble_gap_adv_active","text":"int ble_gap_adv_active ( void )","title":"ble_gap_adv_active"},{"location":"network/ble/ble_hs/ble_gap/functions/ble_gap_adv_active/#description","text":"Indicates whether an advertisement procedure is currently in progress.","title":"Description"},{"location":"network/ble/ble_hs/ble_gap/functions/ble_gap_adv_active/#parameters","text":"None","title":"Parameters"},{"location":"network/ble/ble_hs/ble_gap/functions/ble_gap_adv_active/#returned-values","text":"Value Condition 0 No advertisement procedure in progress. 1 Advertisement procedure in progress.","title":"Returned values"},{"location":"network/ble/ble_hs/ble_gap/functions/ble_gap_adv_rsp_set_fields/","text":"ble_gap_adv_rsp_set_fields int ble_gap_adv_rsp_set_fields ( const struct ble_hs_adv_fields *rsp_fields ) Description Configures the data to include in subsequent scan responses. Parameters Parameter Description adv_fields Specifies the scan response data. Returned values Value Condition 0 Success. BLE_HS_EBUSY Advertising is in progress. BLE_HS_EMSGSIZE The specified data is too large to fit in an advertisement. Core return code Unexpected error.","title":"ble_gap_adv_rsp_set_fields"},{"location":"network/ble/ble_hs/ble_gap/functions/ble_gap_adv_rsp_set_fields/#ble_gap_adv_rsp_set_fields","text":"int ble_gap_adv_rsp_set_fields ( const struct ble_hs_adv_fields *rsp_fields )","title":"ble_gap_adv_rsp_set_fields"},{"location":"network/ble/ble_hs/ble_gap/functions/ble_gap_adv_rsp_set_fields/#description","text":"Configures the data to include in subsequent scan responses.","title":"Description"},{"location":"network/ble/ble_hs/ble_gap/functions/ble_gap_adv_rsp_set_fields/#parameters","text":"Parameter Description adv_fields Specifies the scan response data.","title":"Parameters"},{"location":"network/ble/ble_hs/ble_gap/functions/ble_gap_adv_rsp_set_fields/#returned-values","text":"Value Condition 0 Success. BLE_HS_EBUSY Advertising is in progress. BLE_HS_EMSGSIZE The specified data is too large to fit in an advertisement. Core return code Unexpected error.","title":"Returned values"},{"location":"network/ble/ble_hs/ble_gap/functions/ble_gap_adv_set_fields/","text":"ble_gap_adv_set_fields int ble_gap_adv_set_fields ( const struct ble_hs_adv_fields *adv_fields ) Description Configures the data to include in subsequent advertisements. Parameters Parameter Description adv_fields Specifies the advertisement data. Returned values Value Condition 0 Success. BLE_HS_EBUSY Advertising is in progress. BLE_HS_EMSGSIZE The specified data is too large to fit in an advertisement. Core return code Unexpected error.","title":"ble_gap_adv_set_fields"},{"location":"network/ble/ble_hs/ble_gap/functions/ble_gap_adv_set_fields/#ble_gap_adv_set_fields","text":"int ble_gap_adv_set_fields ( const struct ble_hs_adv_fields *adv_fields )","title":"ble_gap_adv_set_fields"},{"location":"network/ble/ble_hs/ble_gap/functions/ble_gap_adv_set_fields/#description","text":"Configures the data to include in subsequent advertisements.","title":"Description"},{"location":"network/ble/ble_hs/ble_gap/functions/ble_gap_adv_set_fields/#parameters","text":"Parameter Description adv_fields Specifies the advertisement data.","title":"Parameters"},{"location":"network/ble/ble_hs/ble_gap/functions/ble_gap_adv_set_fields/#returned-values","text":"Value Condition 0 Success. BLE_HS_EBUSY Advertising is in progress. BLE_HS_EMSGSIZE The specified data is too large to fit in an advertisement. Core return code Unexpected error.","title":"Returned values"},{"location":"network/ble/ble_hs/ble_gap/functions/ble_gap_adv_start/","text":"ble_gap_adv_start int ble_gap_adv_start ( uint8_t own_addr_type , uint8_t peer_addr_type , const uint8_t *peer_addr , int32_t duration_ms , const struct ble_gap_adv_params *adv_params , ble_gap_event_fn *cb , void *cb_arg ) Description Initiates advertising. Parameters Parameter Description own_addr_type The type of address the stack should use for itself. Valid values are: BLE_ADDR_TYPE_PUBLIC BLE_ADDR_TYPE_RANDOM BLE_ADDR_TYPE_RPA_PUB_DEFAULT BLE_ADDR_TYPE_RPA_RND_DEFAULT peer_addr_type Address type of the peer's identity address. Valid values are: BLE_ADDR_TYPE_PUBLIC BLE_ADDR_TYPE_RANDOM This parameter is ignored unless directed advertising is being used. peer_addr The peer's six-byte identity address. This parameter is ignored unless directed advertising is being used. duration_ms The duration of the advertisement procedure. On expiration, the procedure ends and a BLE_GAP_EVENT_ADV_COMPLETE event is reported. Units are milliseconds. Specify BLE_HS_FOREVER for no expiration. adv_params Additional arguments specifying the particulars of the advertising procedure. cb The callback to associate with this advertising procedure. If advertising ends, the event is reported through this callback. If advertising results in a connection, the connection inherits this callback as its event-reporting mechanism. cb_arg The optional argument to pass to the callback function. Returned values Value Condition 0 Success. Core return code Unexpected error.","title":"ble_gap_adv_start"},{"location":"network/ble/ble_hs/ble_gap/functions/ble_gap_adv_start/#ble_gap_adv_start","text":"int ble_gap_adv_start ( uint8_t own_addr_type , uint8_t peer_addr_type , const uint8_t *peer_addr , int32_t duration_ms , const struct ble_gap_adv_params *adv_params , ble_gap_event_fn *cb , void *cb_arg )","title":"ble_gap_adv_start"},{"location":"network/ble/ble_hs/ble_gap/functions/ble_gap_adv_start/#description","text":"Initiates advertising.","title":"Description"},{"location":"network/ble/ble_hs/ble_gap/functions/ble_gap_adv_start/#parameters","text":"Parameter Description own_addr_type The type of address the stack should use for itself. Valid values are: BLE_ADDR_TYPE_PUBLIC BLE_ADDR_TYPE_RANDOM BLE_ADDR_TYPE_RPA_PUB_DEFAULT BLE_ADDR_TYPE_RPA_RND_DEFAULT peer_addr_type Address type of the peer's identity address. Valid values are: BLE_ADDR_TYPE_PUBLIC BLE_ADDR_TYPE_RANDOM This parameter is ignored unless directed advertising is being used. peer_addr The peer's six-byte identity address. This parameter is ignored unless directed advertising is being used. duration_ms The duration of the advertisement procedure. On expiration, the procedure ends and a BLE_GAP_EVENT_ADV_COMPLETE event is reported. Units are milliseconds. Specify BLE_HS_FOREVER for no expiration. adv_params Additional arguments specifying the particulars of the advertising procedure. cb The callback to associate with this advertising procedure. If advertising ends, the event is reported through this callback. If advertising results in a connection, the connection inherits this callback as its event-reporting mechanism. cb_arg The optional argument to pass to the callback function.","title":"Parameters"},{"location":"network/ble/ble_hs/ble_gap/functions/ble_gap_adv_start/#returned-values","text":"Value Condition 0 Success. Core return code Unexpected error.","title":"Returned values"},{"location":"network/ble/ble_hs/ble_gap/functions/ble_gap_adv_stop/","text":"ble_gap_adv_stop int ble_gap_adv_stop ( void ) Description Stops the currently-active advertising procedure. A success return code indicates that advertising has been fully aborted; a new advertising procedure can be initiated immediately. Parameters None Returned values Value Condition 0 Success. BLE_HS_EALREADY There is no active advertising procedure. Core return code Unexpected error.","title":"ble_gap_adv_stop"},{"location":"network/ble/ble_hs/ble_gap/functions/ble_gap_adv_stop/#ble_gap_adv_stop","text":"int ble_gap_adv_stop ( void )","title":"ble_gap_adv_stop"},{"location":"network/ble/ble_hs/ble_gap/functions/ble_gap_adv_stop/#description","text":"Stops the currently-active advertising procedure. A success return code indicates that advertising has been fully aborted; a new advertising procedure can be initiated immediately.","title":"Description"},{"location":"network/ble/ble_hs/ble_gap/functions/ble_gap_adv_stop/#parameters","text":"None","title":"Parameters"},{"location":"network/ble/ble_hs/ble_gap/functions/ble_gap_adv_stop/#returned-values","text":"Value Condition 0 Success. BLE_HS_EALREADY There is no active advertising procedure. Core return code Unexpected error.","title":"Returned values"},{"location":"network/ble/ble_hs/ble_gap/functions/ble_gap_conn_active/","text":"ble_gap_conn_active int ble_gap_conn_active ( void ) Description Indicates whether a connect procedure is currently in progress. Parameters None Returned values Value Condition 0 No connect procedure in progress. 1 Connect procedure in progress.","title":"ble_gap_conn_active"},{"location":"network/ble/ble_hs/ble_gap/functions/ble_gap_conn_active/#ble_gap_conn_active","text":"int ble_gap_conn_active ( void )","title":"ble_gap_conn_active"},{"location":"network/ble/ble_hs/ble_gap/functions/ble_gap_conn_active/#description","text":"Indicates whether a connect procedure is currently in progress.","title":"Description"},{"location":"network/ble/ble_hs/ble_gap/functions/ble_gap_conn_active/#parameters","text":"None","title":"Parameters"},{"location":"network/ble/ble_hs/ble_gap/functions/ble_gap_conn_active/#returned-values","text":"Value Condition 0 No connect procedure in progress. 1 Connect procedure in progress.","title":"Returned values"},{"location":"network/ble/ble_hs/ble_gap/functions/ble_gap_conn_cancel/","text":"ble_gap_conn_cancel int ble_gap_conn_cancel ( void ) Description Aborts a connect procedure in progress. Parameters None Returned values Value Condition 0 Success. Core return code Unexpected error.","title":"ble_gap_conn_cancel"},{"location":"network/ble/ble_hs/ble_gap/functions/ble_gap_conn_cancel/#ble_gap_conn_cancel","text":"int ble_gap_conn_cancel ( void )","title":"ble_gap_conn_cancel"},{"location":"network/ble/ble_hs/ble_gap/functions/ble_gap_conn_cancel/#description","text":"Aborts a connect procedure in progress.","title":"Description"},{"location":"network/ble/ble_hs/ble_gap/functions/ble_gap_conn_cancel/#parameters","text":"None","title":"Parameters"},{"location":"network/ble/ble_hs/ble_gap/functions/ble_gap_conn_cancel/#returned-values","text":"Value Condition 0 Success. Core return code Unexpected error.","title":"Returned values"},{"location":"network/ble/ble_hs/ble_gap/functions/ble_gap_conn_find/","text":"ble_gap_conn_find int ble_gap_conn_find ( uint16_t handle , struct ble_gap_conn_desc *out_desc ) Description Searches for a connection with the specified handle. If a matching connection is found, the supplied connection descriptor is filled correspondingly. Parameters Parameter Description handle The connection handle to search for. out_desc On success, this is populated with information relating to the matching connection. Pass NULL if you don't need this information. Returned values Value Condition 0 Success. BLE_HS_ENOTCONN No matching connection was found.","title":"ble_gap_conn_find"},{"location":"network/ble/ble_hs/ble_gap/functions/ble_gap_conn_find/#ble_gap_conn_find","text":"int ble_gap_conn_find ( uint16_t handle , struct ble_gap_conn_desc *out_desc )","title":"ble_gap_conn_find"},{"location":"network/ble/ble_hs/ble_gap/functions/ble_gap_conn_find/#description","text":"Searches for a connection with the specified handle. If a matching connection is found, the supplied connection descriptor is filled correspondingly.","title":"Description"},{"location":"network/ble/ble_hs/ble_gap/functions/ble_gap_conn_find/#parameters","text":"Parameter Description handle The connection handle to search for. out_desc On success, this is populated with information relating to the matching connection. Pass NULL if you don't need this information.","title":"Parameters"},{"location":"network/ble/ble_hs/ble_gap/functions/ble_gap_conn_find/#returned-values","text":"Value Condition 0 Success. BLE_HS_ENOTCONN No matching connection was found.","title":"Returned values"},{"location":"network/ble/ble_hs/ble_gap/functions/ble_gap_conn_rssi/","text":"ble_gap_conn_rssi int ble_gap_conn_rssi ( uint16_t conn_handle , int8_t *out_rssi ) Description Retrieves the most-recently measured RSSI for the specified connection. A connection's RSSI is updated whenever a data channel PDU is received. Parameters Parameter Description conn_handle Specifies the connection to query. out_rssi On success, the retrieved RSSI is written here. Returned values Value Condition 0 Success. HCI return code The controller rejected the request. Core return code Unexpected error.","title":"ble_gap_conn_rssi"},{"location":"network/ble/ble_hs/ble_gap/functions/ble_gap_conn_rssi/#ble_gap_conn_rssi","text":"int ble_gap_conn_rssi ( uint16_t conn_handle , int8_t *out_rssi )","title":"ble_gap_conn_rssi"},{"location":"network/ble/ble_hs/ble_gap/functions/ble_gap_conn_rssi/#description","text":"Retrieves the most-recently measured RSSI for the specified connection. A connection's RSSI is updated whenever a data channel PDU is received.","title":"Description"},{"location":"network/ble/ble_hs/ble_gap/functions/ble_gap_conn_rssi/#parameters","text":"Parameter Description conn_handle Specifies the connection to query. out_rssi On success, the retrieved RSSI is written here.","title":"Parameters"},{"location":"network/ble/ble_hs/ble_gap/functions/ble_gap_conn_rssi/#returned-values","text":"Value Condition 0 Success. HCI return code The controller rejected the request. Core return code Unexpected error.","title":"Returned values"},{"location":"network/ble/ble_hs/ble_gap/functions/ble_gap_connect/","text":"ble_gap_connect int ble_gap_connect ( uint8_t own_addr_type , uint8_t peer_addr_type , const uint8_t *peer_addr , int32_t duration_ms , const struct ble_gap_conn_params *conn_params , ble_gap_event_fn *cb , void *cb_arg ) Description Initiates a connect procedure. Parameters Parameter Description own_addr_type The type of address the stack should use for itself during connection establishment. BLE_ADDR_TYPE_PUBLIC BLE_ADDR_TYPE_RANDOM BLE_ADDR_TYPE_RPA_PUB_DEFAULT BLE_ADDR_TYPE_RPA_RND_DEFAULT peer_addr_type The peer's address type. One of: BLE_HCI_CONN_PEER_ADDR_PUBLIC BLE_HCI_CONN_PEER_ADDR_RANDOM BLE_HCI_CONN_PEER_ADDR_PUBLIC_IDENT BLE_HCI_CONN_PEER_ADDR_RANDOM_IDENT BLE_GAP_ADDR_TYPE_WL peer_addr The identity address of the peer to connect to. This parameter is ignored when the white list is used. duration_ms The duration of the discovery procedure. On expiration, the procedure ends and a BLE_GAP_EVENT_DISC_COMPLETE event is reported. Units are milliseconds. conn_params Additional arguments specifying the particulars of the connect procedure. Specify null for default values. cb The callback to associate with this connect procedure. When the connect procedure completes, the result is reported through this callback. If the connect procedure succeeds, the connection inherits this callback as its event-reporting mechanism. cb_arg The optional argument to pass to the callback function. Returned values Value Condition 0 Success. Core return code Unexpected error.","title":"ble_gap_connect"},{"location":"network/ble/ble_hs/ble_gap/functions/ble_gap_connect/#ble_gap_connect","text":"int ble_gap_connect ( uint8_t own_addr_type , uint8_t peer_addr_type , const uint8_t *peer_addr , int32_t duration_ms , const struct ble_gap_conn_params *conn_params , ble_gap_event_fn *cb , void *cb_arg )","title":"ble_gap_connect"},{"location":"network/ble/ble_hs/ble_gap/functions/ble_gap_connect/#description","text":"Initiates a connect procedure.","title":"Description"},{"location":"network/ble/ble_hs/ble_gap/functions/ble_gap_connect/#parameters","text":"Parameter Description own_addr_type The type of address the stack should use for itself during connection establishment. BLE_ADDR_TYPE_PUBLIC BLE_ADDR_TYPE_RANDOM BLE_ADDR_TYPE_RPA_PUB_DEFAULT BLE_ADDR_TYPE_RPA_RND_DEFAULT peer_addr_type The peer's address type. One of: BLE_HCI_CONN_PEER_ADDR_PUBLIC BLE_HCI_CONN_PEER_ADDR_RANDOM BLE_HCI_CONN_PEER_ADDR_PUBLIC_IDENT BLE_HCI_CONN_PEER_ADDR_RANDOM_IDENT BLE_GAP_ADDR_TYPE_WL peer_addr The identity address of the peer to connect to. This parameter is ignored when the white list is used. duration_ms The duration of the discovery procedure. On expiration, the procedure ends and a BLE_GAP_EVENT_DISC_COMPLETE event is reported. Units are milliseconds. conn_params Additional arguments specifying the particulars of the connect procedure. Specify null for default values. cb The callback to associate with this connect procedure. When the connect procedure completes, the result is reported through this callback. If the connect procedure succeeds, the connection inherits this callback as its event-reporting mechanism. cb_arg The optional argument to pass to the callback function.","title":"Parameters"},{"location":"network/ble/ble_hs/ble_gap/functions/ble_gap_connect/#returned-values","text":"Value Condition 0 Success. Core return code Unexpected error.","title":"Returned values"},{"location":"network/ble/ble_hs/ble_gap/functions/ble_gap_disc/","text":"ble_gap_disc int ble_gap_disc ( uint8_t own_addr_type , int32_t duration_ms , const struct ble_gap_disc_params *disc_params , ble_gap_event_fn *cb , void *cb_arg ) Description Performs the Limited or General Discovery Procedures. Parameters Parameter Description own_addr_type The type of address the stack should use for itself when sending scan requests. Valid values are: BLE_ADDR_TYPE_PUBLIC BLE_ADDR_TYPE_RANDOM BLE_ADDR_TYPE_RPA_PUB_DEFAULT BLE_ADDR_TYPE_RPA_RND_DEFAULT This parameter is ignored unless active scanning is being used. duration_ms The duration of the discovery procedure. On expiration, the procedure ends and a BLE_GAP_EVENT_DISC_COMPLETE event is reported. Units are milliseconds. Specify BLE_HS_FOREVER for no expiration. disc_params Additional arguments specifying the particulars of the discovery procedure. cb The callback to associate with this discovery procedure. Advertising reports and discovery termination events are reported through this callback. cb_arg The optional argument to pass to the callback function. Returned values Value Condition 0 Success. Core return code Unexpected error.","title":"ble_gap_disc"},{"location":"network/ble/ble_hs/ble_gap/functions/ble_gap_disc/#ble_gap_disc","text":"int ble_gap_disc ( uint8_t own_addr_type , int32_t duration_ms , const struct ble_gap_disc_params *disc_params , ble_gap_event_fn *cb , void *cb_arg )","title":"ble_gap_disc"},{"location":"network/ble/ble_hs/ble_gap/functions/ble_gap_disc/#description","text":"Performs the Limited or General Discovery Procedures.","title":"Description"},{"location":"network/ble/ble_hs/ble_gap/functions/ble_gap_disc/#parameters","text":"Parameter Description own_addr_type The type of address the stack should use for itself when sending scan requests. Valid values are: BLE_ADDR_TYPE_PUBLIC BLE_ADDR_TYPE_RANDOM BLE_ADDR_TYPE_RPA_PUB_DEFAULT BLE_ADDR_TYPE_RPA_RND_DEFAULT This parameter is ignored unless active scanning is being used. duration_ms The duration of the discovery procedure. On expiration, the procedure ends and a BLE_GAP_EVENT_DISC_COMPLETE event is reported. Units are milliseconds. Specify BLE_HS_FOREVER for no expiration. disc_params Additional arguments specifying the particulars of the discovery procedure. cb The callback to associate with this discovery procedure. Advertising reports and discovery termination events are reported through this callback. cb_arg The optional argument to pass to the callback function.","title":"Parameters"},{"location":"network/ble/ble_hs/ble_gap/functions/ble_gap_disc/#returned-values","text":"Value Condition 0 Success. Core return code Unexpected error.","title":"Returned values"},{"location":"network/ble/ble_hs/ble_gap/functions/ble_gap_disc_active/","text":"ble_gap_disc_active int ble_gap_disc_active ( void ) Description Indicates whether a discovery procedure is currently in progress. Parameters None Returned values Value Condition 0 No discovery procedure in progress. 1 Discovery procedure in progress.","title":"ble_gap_disc_active"},{"location":"network/ble/ble_hs/ble_gap/functions/ble_gap_disc_active/#ble_gap_disc_active","text":"int ble_gap_disc_active ( void )","title":"ble_gap_disc_active"},{"location":"network/ble/ble_hs/ble_gap/functions/ble_gap_disc_active/#description","text":"Indicates whether a discovery procedure is currently in progress.","title":"Description"},{"location":"network/ble/ble_hs/ble_gap/functions/ble_gap_disc_active/#parameters","text":"None","title":"Parameters"},{"location":"network/ble/ble_hs/ble_gap/functions/ble_gap_disc_active/#returned-values","text":"Value Condition 0 No discovery procedure in progress. 1 Discovery procedure in progress.","title":"Returned values"},{"location":"network/ble/ble_hs/ble_gap/functions/ble_gap_disc_cancel/","text":"ble_gap_disc_cancel int ble_gap_disc_cancel ( void ) Description Cancels the discovery procedure currently in progress. A success return code indicates that scanning has been fully aborted; a new discovery or connect procedure can be initiated immediately. Parameters None Returned values Value Condition 0 Success. BLE_HS_EALREADY There is no discovery procedure to cancel. Core return code Unexpected error.","title":"ble_gap_disc_cancel"},{"location":"network/ble/ble_hs/ble_gap/functions/ble_gap_disc_cancel/#ble_gap_disc_cancel","text":"int ble_gap_disc_cancel ( void )","title":"ble_gap_disc_cancel"},{"location":"network/ble/ble_hs/ble_gap/functions/ble_gap_disc_cancel/#description","text":"Cancels the discovery procedure currently in progress. A success return code indicates that scanning has been fully aborted; a new discovery or connect procedure can be initiated immediately.","title":"Description"},{"location":"network/ble/ble_hs/ble_gap/functions/ble_gap_disc_cancel/#parameters","text":"None","title":"Parameters"},{"location":"network/ble/ble_hs/ble_gap/functions/ble_gap_disc_cancel/#returned-values","text":"Value Condition 0 Success. BLE_HS_EALREADY There is no discovery procedure to cancel. Core return code Unexpected error.","title":"Returned values"},{"location":"network/ble/ble_hs/ble_gap/functions/ble_gap_security_initiate/","text":"ble_gap_security_initiate int ble_gap_security_initiate ( uint16_t conn_handle ) Description Initiates the GAP encryption procedure. Parameters Parameter Description conn_handle The handle corresponding to the connection to encrypt. Returned values Value Condition 0 Success. BLE_HS_ENOTCONN The there is no connection with the specified handle. BLE_HS_EALREADY An encrpytion procedure for this connection is already in progress. Core return code Unexpected error.","title":"ble_gap_security_initiate"},{"location":"network/ble/ble_hs/ble_gap/functions/ble_gap_security_initiate/#ble_gap_security_initiate","text":"int ble_gap_security_initiate ( uint16_t conn_handle )","title":"ble_gap_security_initiate"},{"location":"network/ble/ble_hs/ble_gap/functions/ble_gap_security_initiate/#description","text":"Initiates the GAP encryption procedure.","title":"Description"},{"location":"network/ble/ble_hs/ble_gap/functions/ble_gap_security_initiate/#parameters","text":"Parameter Description conn_handle The handle corresponding to the connection to encrypt.","title":"Parameters"},{"location":"network/ble/ble_hs/ble_gap/functions/ble_gap_security_initiate/#returned-values","text":"Value Condition 0 Success. BLE_HS_ENOTCONN The there is no connection with the specified handle. BLE_HS_EALREADY An encrpytion procedure for this connection is already in progress. Core return code Unexpected error.","title":"Returned values"},{"location":"network/ble/ble_hs/ble_gap/functions/ble_gap_terminate/","text":"ble_gap_terminate int ble_gap_terminate ( uint16_t conn_handle , uint8_t hci_reason ) Description Terminates an established connection. Parameters Parameter Description conn_handle The handle corresponding to the connection to terminate. hci_reason The HCI error code to indicate as the reason for termination. Returned values Value Condition 0 Success. BLE_HS_ENOTCONN There is no connection with the specified handle. Core return code Unexpected error.","title":"ble_gap_terminate"},{"location":"network/ble/ble_hs/ble_gap/functions/ble_gap_terminate/#ble_gap_terminate","text":"int ble_gap_terminate ( uint16_t conn_handle , uint8_t hci_reason )","title":"ble_gap_terminate"},{"location":"network/ble/ble_hs/ble_gap/functions/ble_gap_terminate/#description","text":"Terminates an established connection.","title":"Description"},{"location":"network/ble/ble_hs/ble_gap/functions/ble_gap_terminate/#parameters","text":"Parameter Description conn_handle The handle corresponding to the connection to terminate. hci_reason The HCI error code to indicate as the reason for termination.","title":"Parameters"},{"location":"network/ble/ble_hs/ble_gap/functions/ble_gap_terminate/#returned-values","text":"Value Condition 0 Success. BLE_HS_ENOTCONN There is no connection with the specified handle. Core return code Unexpected error.","title":"Returned values"},{"location":"network/ble/ble_hs/ble_gap/functions/ble_gap_update_params/","text":"ble_gap_update_params int ble_gap_update_params ( uint16_t conn_handle , const struct ble_gap_upd_params *params ) Description Initiates a connection parameter update procedure. Parameters Parameter Description conn_handle The handle corresponding to the connection to update. params The connection parameters to attempt to update to. Returned values Value Condition 0 Success. BLE_HS_ENOTCONN The there is no connection with the specified handle. BLE_HS_EALREADY A connection update procedure for this connection is already in progress. Core return code Unexpected error.","title":"ble_gap_update_params"},{"location":"network/ble/ble_hs/ble_gap/functions/ble_gap_update_params/#ble_gap_update_params","text":"int ble_gap_update_params ( uint16_t conn_handle , const struct ble_gap_upd_params *params )","title":"ble_gap_update_params"},{"location":"network/ble/ble_hs/ble_gap/functions/ble_gap_update_params/#description","text":"Initiates a connection parameter update procedure.","title":"Description"},{"location":"network/ble/ble_hs/ble_gap/functions/ble_gap_update_params/#parameters","text":"Parameter Description conn_handle The handle corresponding to the connection to update. params The connection parameters to attempt to update to.","title":"Parameters"},{"location":"network/ble/ble_hs/ble_gap/functions/ble_gap_update_params/#returned-values","text":"Value Condition 0 Success. BLE_HS_ENOTCONN The there is no connection with the specified handle. BLE_HS_EALREADY A connection update procedure for this connection is already in progress. Core return code Unexpected error.","title":"Returned values"},{"location":"network/ble/ble_hs/ble_gap/functions/ble_gap_wl_set/","text":"ble_gap_wl_set int ble_gap_wl_set ( const struct ble_gap_white_entry *white_list , uint8_t white_list_count ) Description Overwrites the controller's white list with the specified contents. Parameters Parameter Description white_list The entries to write to the white list. white_list_count The number of entries in the white list. Returned values Value Condition 0 Success. Core return code Unexpected error.","title":"ble_gap_wl_set"},{"location":"network/ble/ble_hs/ble_gap/functions/ble_gap_wl_set/#ble_gap_wl_set","text":"int ble_gap_wl_set ( const struct ble_gap_white_entry *white_list , uint8_t white_list_count )","title":"ble_gap_wl_set"},{"location":"network/ble/ble_hs/ble_gap/functions/ble_gap_wl_set/#description","text":"Overwrites the controller's white list with the specified contents.","title":"Description"},{"location":"network/ble/ble_hs/ble_gap/functions/ble_gap_wl_set/#parameters","text":"Parameter Description white_list The entries to write to the white list. white_list_count The number of entries in the white list.","title":"Parameters"},{"location":"network/ble/ble_hs/ble_gap/functions/ble_gap_wl_set/#returned-values","text":"Value Condition 0 Success. Core return code Unexpected error.","title":"Returned values"},{"location":"network/ble/ble_hs/ble_gattc/ble_gattc/","text":"NimBLE Host GATT Client Reference Introduction The Generic Attribute Profile (GATT) manages all activities involving services, characteristics, and descriptors. The client half of the GATT API initiates GATT procedures. Header #include \"host/ble_hs.h\" Definitions BLE host GATT client definitions Functions Function Description ble_gattc_disc_all_chrs Initiates GATT procedure: Discover All Characteristics of a Service. ble_gattc_disc_all_dscs Initiates GATT procedure: Discover All Characteristic Descriptors. ble_gattc_disc_all_svcs Initiates GATT procedure: Discover All Primary Services. ble_gattc_disc_chrs_by_uuid Initiates GATT procedure: Discover Characteristics by UUID. ble_gattc_disc_svc_by_uuid Initiates GATT procedure: Discover Primary Service by Service UUID. ble_gattc_exchange_mtu Initiates GATT procedure: Exchange MTU. ble_gattc_find_inc_svcs Initiates GATT procedure: Find Included Services. ble_gattc_indicate Sends a characteristic indication. ble_gattc_notify Sends a characteristic notification. ble_gattc_notify_custom Sends a \"free-form\" characteristic notification. ble_gattc_read Initiates GATT procedure: Read Characteristic Value. ble_gattc_read_by_uuid Initiates GATT procedure: Read Using Characteristic UUID. ble_gattc_read_long Initiates GATT procedure: Read Long Characteristic Values. ble_gattc_read_mult Initiates GATT procedure: Read Multiple Characteristic Values. ble_gattc_write Initiates GATT procedure: Write Characteristic Value. ble_gattc_write_flat Initiates GATT procedure: Write Characteristic Value (flat buffer version). ble_gattc_write_long Initiates GATT procedure: Write Long Characteristic Values. ble_gattc_write_no_rsp Initiates GATT procedure: Write Without Response. ble_gattc_write_no_rsp_flat Initiates GATT procedure: Write Without Response. ble_gattc_write_reliable Initiates GATT procedure: Reliable Writes.","title":"toc"},{"location":"network/ble/ble_hs/ble_gattc/ble_gattc/#nimble-host-gatt-client-reference","text":"","title":"NimBLE Host GATT Client Reference"},{"location":"network/ble/ble_hs/ble_gattc/ble_gattc/#introduction","text":"The Generic Attribute Profile (GATT) manages all activities involving services, characteristics, and descriptors. The client half of the GATT API initiates GATT procedures.","title":"Introduction"},{"location":"network/ble/ble_hs/ble_gattc/ble_gattc/#header","text":"#include \"host/ble_hs.h\"","title":"Header"},{"location":"network/ble/ble_hs/ble_gattc/ble_gattc/#definitions","text":"BLE host GATT client definitions","title":"Definitions"},{"location":"network/ble/ble_hs/ble_gattc/ble_gattc/#functions","text":"Function Description ble_gattc_disc_all_chrs Initiates GATT procedure: Discover All Characteristics of a Service. ble_gattc_disc_all_dscs Initiates GATT procedure: Discover All Characteristic Descriptors. ble_gattc_disc_all_svcs Initiates GATT procedure: Discover All Primary Services. ble_gattc_disc_chrs_by_uuid Initiates GATT procedure: Discover Characteristics by UUID. ble_gattc_disc_svc_by_uuid Initiates GATT procedure: Discover Primary Service by Service UUID. ble_gattc_exchange_mtu Initiates GATT procedure: Exchange MTU. ble_gattc_find_inc_svcs Initiates GATT procedure: Find Included Services. ble_gattc_indicate Sends a characteristic indication. ble_gattc_notify Sends a characteristic notification. ble_gattc_notify_custom Sends a \"free-form\" characteristic notification. ble_gattc_read Initiates GATT procedure: Read Characteristic Value. ble_gattc_read_by_uuid Initiates GATT procedure: Read Using Characteristic UUID. ble_gattc_read_long Initiates GATT procedure: Read Long Characteristic Values. ble_gattc_read_mult Initiates GATT procedure: Read Multiple Characteristic Values. ble_gattc_write Initiates GATT procedure: Write Characteristic Value. ble_gattc_write_flat Initiates GATT procedure: Write Characteristic Value (flat buffer version). ble_gattc_write_long Initiates GATT procedure: Write Long Characteristic Values. ble_gattc_write_no_rsp Initiates GATT procedure: Write Without Response. ble_gattc_write_no_rsp_flat Initiates GATT procedure: Write Without Response. ble_gattc_write_reliable Initiates GATT procedure: Reliable Writes.","title":"Functions"},{"location":"network/ble/ble_hs/ble_gattc/definitions/ble_gattc_defs/","text":"GATT Client Definitions struct ble_gatt_error { uint16_t status ; uint16_t att_handle ; }; struct ble_gatt_svc { uint16_t start_handle ; uint16_t end_handle ; uint8_t uuid128 [ 16 ]; }; struct ble_gatt_attr { uint16_t handle ; uint16_t offset ; struct os_mbuf *om ; }; struct ble_gatt_chr { uint16_t def_handle ; uint16_t val_handle ; uint8_t properties ; uint8_t uuid128 [ 16 ]; }; struct ble_gatt_dsc { uint16_t handle ; uint8_t uuid128 [ 16 ]; }; typedef int ble_gatt_mtu_fn ( uint16_t conn_handle , const struct ble_gatt_error *error , uint16_t mtu , void *arg ); typedef int ble_gatt_disc_svc_fn ( uint16_t conn_handle , const struct ble_gatt_error *error , const struct ble_gatt_svc *service , void *arg ); /** * The host will free the attribute mbuf automatically after the callback is * executed. The application can take ownership of the mbuf and prevent it * from being freed by assigning NULL to attr->om. */ typedef int ble_gatt_attr_fn ( uint16_t conn_handle , const struct ble_gatt_error *error , struct ble_gatt_attr *attr , void *arg ); /** * The host will free the attribute mbufs automatically after the callback is * executed. The application can take ownership of the mbufs and prevent them * from being freed by assigning NULL to each attribute's om field. */ typedef int ble_gatt_reliable_attr_fn ( uint16_t conn_handle , const struct ble_gatt_error *error , struct ble_gatt_attr *attrs , uint8_t num_attrs , void *arg ); typedef int ble_gatt_chr_fn ( uint16_t conn_handle , const struct ble_gatt_error *error , const struct ble_gatt_chr *chr , void *arg ); typedef int ble_gatt_dsc_fn ( uint16_t conn_handle , const struct ble_gatt_error *error , uint16_t chr_def_handle , const struct ble_gatt_dsc *dsc , void *arg );","title":"GATT client definitions"},{"location":"network/ble/ble_hs/ble_gattc/definitions/ble_gattc_defs/#gatt-client-definitions","text":"struct ble_gatt_error { uint16_t status ; uint16_t att_handle ; }; struct ble_gatt_svc { uint16_t start_handle ; uint16_t end_handle ; uint8_t uuid128 [ 16 ]; }; struct ble_gatt_attr { uint16_t handle ; uint16_t offset ; struct os_mbuf *om ; }; struct ble_gatt_chr { uint16_t def_handle ; uint16_t val_handle ; uint8_t properties ; uint8_t uuid128 [ 16 ]; }; struct ble_gatt_dsc { uint16_t handle ; uint8_t uuid128 [ 16 ]; }; typedef int ble_gatt_mtu_fn ( uint16_t conn_handle , const struct ble_gatt_error *error , uint16_t mtu , void *arg ); typedef int ble_gatt_disc_svc_fn ( uint16_t conn_handle , const struct ble_gatt_error *error , const struct ble_gatt_svc *service , void *arg ); /** * The host will free the attribute mbuf automatically after the callback is * executed. The application can take ownership of the mbuf and prevent it * from being freed by assigning NULL to attr->om. */ typedef int ble_gatt_attr_fn ( uint16_t conn_handle , const struct ble_gatt_error *error , struct ble_gatt_attr *attr , void *arg ); /** * The host will free the attribute mbufs automatically after the callback is * executed. The application can take ownership of the mbufs and prevent them * from being freed by assigning NULL to each attribute's om field. */ typedef int ble_gatt_reliable_attr_fn ( uint16_t conn_handle , const struct ble_gatt_error *error , struct ble_gatt_attr *attrs , uint8_t num_attrs , void *arg ); typedef int ble_gatt_chr_fn ( uint16_t conn_handle , const struct ble_gatt_error *error , const struct ble_gatt_chr *chr , void *arg ); typedef int ble_gatt_dsc_fn ( uint16_t conn_handle , const struct ble_gatt_error *error , uint16_t chr_def_handle , const struct ble_gatt_dsc *dsc , void *arg );","title":"GATT Client Definitions"},{"location":"network/ble/ble_hs/ble_gattc/functions/ble_gattc_disc_all_chrs/","text":"ble_gattc_disc_all_chrs int ble_gattc_disc_all_chrs ( uint16_t conn_handle , uint16_t start_handle , uint16_t end_handle , ble_gatt_chr_fn *cb , void *cb_arg ) Description Initiates GATT procedure: Discover All Characteristics of a Service. Parameters Parameter Description conn_handle The connection over which to execute the procedure. start_handle The handle to begin the search at (generally the service definition handle). end_handle The handle to end the search at (generally the last handle in the service). cb The function to call to report procedure status updates; null for no callback. cb_arg The optional argument to pass to the callback function. Returned values Value Condition 0 Success. Core return code Unexpected error.","title":"ble_gattc_disc_all_chrs"},{"location":"network/ble/ble_hs/ble_gattc/functions/ble_gattc_disc_all_chrs/#ble_gattc_disc_all_chrs","text":"int ble_gattc_disc_all_chrs ( uint16_t conn_handle , uint16_t start_handle , uint16_t end_handle , ble_gatt_chr_fn *cb , void *cb_arg )","title":"ble_gattc_disc_all_chrs"},{"location":"network/ble/ble_hs/ble_gattc/functions/ble_gattc_disc_all_chrs/#description","text":"Initiates GATT procedure: Discover All Characteristics of a Service.","title":"Description"},{"location":"network/ble/ble_hs/ble_gattc/functions/ble_gattc_disc_all_chrs/#parameters","text":"Parameter Description conn_handle The connection over which to execute the procedure. start_handle The handle to begin the search at (generally the service definition handle). end_handle The handle to end the search at (generally the last handle in the service). cb The function to call to report procedure status updates; null for no callback. cb_arg The optional argument to pass to the callback function.","title":"Parameters"},{"location":"network/ble/ble_hs/ble_gattc/functions/ble_gattc_disc_all_chrs/#returned-values","text":"Value Condition 0 Success. Core return code Unexpected error.","title":"Returned values"},{"location":"network/ble/ble_hs/ble_gattc/functions/ble_gattc_disc_all_dscs/","text":"ble_gattc_disc_all_dscs int ble_gattc_disc_all_dscs ( uint16_t conn_handle , uint16_t chr_val_handle , uint16_t chr_end_handle , ble_gatt_dsc_fn *cb , void *cb_arg ) Description Initiates GATT procedure: Discover All Characteristic Descriptors. Parameters Parameter Description conn_handle The connection over which to execute the procedure. chr_val_handle The handle of the characteristic value attribute. chr_end_handle The last handle in the characteristic definition. cb The function to call to report procedure status updates; null for no callback. cb_arg The optional argument to pass to the callback function. Returned values Value Condition 0 Success. Core return code Unexpected error.","title":"ble_gattc_disc_all_dscs"},{"location":"network/ble/ble_hs/ble_gattc/functions/ble_gattc_disc_all_dscs/#ble_gattc_disc_all_dscs","text":"int ble_gattc_disc_all_dscs ( uint16_t conn_handle , uint16_t chr_val_handle , uint16_t chr_end_handle , ble_gatt_dsc_fn *cb , void *cb_arg )","title":"ble_gattc_disc_all_dscs"},{"location":"network/ble/ble_hs/ble_gattc/functions/ble_gattc_disc_all_dscs/#description","text":"Initiates GATT procedure: Discover All Characteristic Descriptors.","title":"Description"},{"location":"network/ble/ble_hs/ble_gattc/functions/ble_gattc_disc_all_dscs/#parameters","text":"Parameter Description conn_handle The connection over which to execute the procedure. chr_val_handle The handle of the characteristic value attribute. chr_end_handle The last handle in the characteristic definition. cb The function to call to report procedure status updates; null for no callback. cb_arg The optional argument to pass to the callback function.","title":"Parameters"},{"location":"network/ble/ble_hs/ble_gattc/functions/ble_gattc_disc_all_dscs/#returned-values","text":"Value Condition 0 Success. Core return code Unexpected error.","title":"Returned values"},{"location":"network/ble/ble_hs/ble_gattc/functions/ble_gattc_disc_all_svcs/","text":"ble_gattc_disc_all_svcs int ble_gattc_disc_all_svcs ( uint16_t conn_handle , ble_gatt_disc_svc_fn *cb , void *cb_arg ) Description Initiates GATT procedure: Discover All Primary Services. Parameters Parameter Description conn_handle The connection over which to execute the procedure. cb The function to call to report procedure status updates; null for no callback. cb_arg The optional argument to pass to the callback function. Returned values None","title":"ble_gattc_disc_all_svcs"},{"location":"network/ble/ble_hs/ble_gattc/functions/ble_gattc_disc_all_svcs/#ble_gattc_disc_all_svcs","text":"int ble_gattc_disc_all_svcs ( uint16_t conn_handle , ble_gatt_disc_svc_fn *cb , void *cb_arg )","title":"ble_gattc_disc_all_svcs"},{"location":"network/ble/ble_hs/ble_gattc/functions/ble_gattc_disc_all_svcs/#description","text":"Initiates GATT procedure: Discover All Primary Services.","title":"Description"},{"location":"network/ble/ble_hs/ble_gattc/functions/ble_gattc_disc_all_svcs/#parameters","text":"Parameter Description conn_handle The connection over which to execute the procedure. cb The function to call to report procedure status updates; null for no callback. cb_arg The optional argument to pass to the callback function.","title":"Parameters"},{"location":"network/ble/ble_hs/ble_gattc/functions/ble_gattc_disc_all_svcs/#returned-values","text":"None","title":"Returned values"},{"location":"network/ble/ble_hs/ble_gattc/functions/ble_gattc_disc_chrs_by_uuid/","text":"ble_gattc_disc_chrs_by_uuid int ble_gattc_disc_chrs_by_uuid ( uint16_t conn_handle , uint16_t start_handle , uint16_t end_handle , const void *uuid128 , ble_gatt_chr_fn *cb , void *cb_arg ) Description Initiates GATT procedure: Discover Characteristics by UUID. Parameters Parameter Description conn_handle The connection over which to execute the procedure. start_handle The handle to begin the search at (generally the service definition handle). end_handle The handle to end the search at (generally the last handle in the service). chr_uuid128 The 128-bit UUID of the characteristic to discover. cb The function to call to report procedure status updates; null for no callback. cb_arg The optional argument to pass to the callback function. Returned values Value Condition 0 Success. Core return code Unexpected error.","title":"ble_gattc_disc_chrs_by_uuid"},{"location":"network/ble/ble_hs/ble_gattc/functions/ble_gattc_disc_chrs_by_uuid/#ble_gattc_disc_chrs_by_uuid","text":"int ble_gattc_disc_chrs_by_uuid ( uint16_t conn_handle , uint16_t start_handle , uint16_t end_handle , const void *uuid128 , ble_gatt_chr_fn *cb , void *cb_arg )","title":"ble_gattc_disc_chrs_by_uuid"},{"location":"network/ble/ble_hs/ble_gattc/functions/ble_gattc_disc_chrs_by_uuid/#description","text":"Initiates GATT procedure: Discover Characteristics by UUID.","title":"Description"},{"location":"network/ble/ble_hs/ble_gattc/functions/ble_gattc_disc_chrs_by_uuid/#parameters","text":"Parameter Description conn_handle The connection over which to execute the procedure. start_handle The handle to begin the search at (generally the service definition handle). end_handle The handle to end the search at (generally the last handle in the service). chr_uuid128 The 128-bit UUID of the characteristic to discover. cb The function to call to report procedure status updates; null for no callback. cb_arg The optional argument to pass to the callback function.","title":"Parameters"},{"location":"network/ble/ble_hs/ble_gattc/functions/ble_gattc_disc_chrs_by_uuid/#returned-values","text":"Value Condition 0 Success. Core return code Unexpected error.","title":"Returned values"},{"location":"network/ble/ble_hs/ble_gattc/functions/ble_gattc_disc_svc_by_uuid/","text":"ble_gattc_disc_svc_by_uuid int ble_gattc_disc_svc_by_uuid ( uint16_t conn_handle , const void *svc_uuid128 , ble_gatt_disc_svc_fn *cb , void *cb_arg ) Description Initiates GATT procedure: Discover Primary Service by Service UUID. Parameters Parameter Description conn_handle The connection over which to execute the procedure. service_uuid128 The 128-bit UUID of the service to discover. cb The function to call to report procedure status updates; null for no callback. cb_arg The optional argument to pass to the callback function. Returned values Value Condition 0 Success. Core return code Unexpected error.","title":"ble_gattc_disc_svc_by_uuid"},{"location":"network/ble/ble_hs/ble_gattc/functions/ble_gattc_disc_svc_by_uuid/#ble_gattc_disc_svc_by_uuid","text":"int ble_gattc_disc_svc_by_uuid ( uint16_t conn_handle , const void *svc_uuid128 , ble_gatt_disc_svc_fn *cb , void *cb_arg )","title":"ble_gattc_disc_svc_by_uuid"},{"location":"network/ble/ble_hs/ble_gattc/functions/ble_gattc_disc_svc_by_uuid/#description","text":"Initiates GATT procedure: Discover Primary Service by Service UUID.","title":"Description"},{"location":"network/ble/ble_hs/ble_gattc/functions/ble_gattc_disc_svc_by_uuid/#parameters","text":"Parameter Description conn_handle The connection over which to execute the procedure. service_uuid128 The 128-bit UUID of the service to discover. cb The function to call to report procedure status updates; null for no callback. cb_arg The optional argument to pass to the callback function.","title":"Parameters"},{"location":"network/ble/ble_hs/ble_gattc/functions/ble_gattc_disc_svc_by_uuid/#returned-values","text":"Value Condition 0 Success. Core return code Unexpected error.","title":"Returned values"},{"location":"network/ble/ble_hs/ble_gattc/functions/ble_gattc_exchange_mtu/","text":"ble_gattc_exchange_mtu int ble_gattc_exchange_mtu ( uint16_t conn_handle , ble_gatt_mtu_fn *cb , void *cb_arg ) Description Initiates GATT procedure: Exchange MTU. Parameters Parameter Description conn_handle The connection over which to execute the procedure. cb The function to call to report procedure status updates; null for no callback. cb_arg The optional argument to pass to the callback function. Returned values Value Condition 0 Success. Core return code Unexpected error.","title":"ble_gattc_exchange_mtu"},{"location":"network/ble/ble_hs/ble_gattc/functions/ble_gattc_exchange_mtu/#ble_gattc_exchange_mtu","text":"int ble_gattc_exchange_mtu ( uint16_t conn_handle , ble_gatt_mtu_fn *cb , void *cb_arg )","title":"ble_gattc_exchange_mtu"},{"location":"network/ble/ble_hs/ble_gattc/functions/ble_gattc_exchange_mtu/#description","text":"Initiates GATT procedure: Exchange MTU.","title":"Description"},{"location":"network/ble/ble_hs/ble_gattc/functions/ble_gattc_exchange_mtu/#parameters","text":"Parameter Description conn_handle The connection over which to execute the procedure. cb The function to call to report procedure status updates; null for no callback. cb_arg The optional argument to pass to the callback function.","title":"Parameters"},{"location":"network/ble/ble_hs/ble_gattc/functions/ble_gattc_exchange_mtu/#returned-values","text":"Value Condition 0 Success. Core return code Unexpected error.","title":"Returned values"},{"location":"network/ble/ble_hs/ble_gattc/functions/ble_gattc_find_inc_svcs/","text":"ble_gattc_find_inc_svcs int ble_gattc_find_inc_svcs ( uint16_t conn_handle , uint16_t start_handle , uint16_t end_handle , ble_gatt_disc_svc_fn *cb , void *cb_arg ) Description Initiates GATT procedure: Find Included Services. Parameters Parameter Description conn_handle The connection over which to execute the procedure. start_handle The handle to begin the search at (generally the service definition handle). end_handle The handle to end the search at (generally the last handle in the service). cb The function to call to report procedure status updates; null for no callback. cb_arg The optional argument to pass to the callback function. Returned values Value Condition 0 Success. Core return code Unexpected error.","title":"ble_gattc_find_inc_svcs"},{"location":"network/ble/ble_hs/ble_gattc/functions/ble_gattc_find_inc_svcs/#ble_gattc_find_inc_svcs","text":"int ble_gattc_find_inc_svcs ( uint16_t conn_handle , uint16_t start_handle , uint16_t end_handle , ble_gatt_disc_svc_fn *cb , void *cb_arg )","title":"ble_gattc_find_inc_svcs"},{"location":"network/ble/ble_hs/ble_gattc/functions/ble_gattc_find_inc_svcs/#description","text":"Initiates GATT procedure: Find Included Services.","title":"Description"},{"location":"network/ble/ble_hs/ble_gattc/functions/ble_gattc_find_inc_svcs/#parameters","text":"Parameter Description conn_handle The connection over which to execute the procedure. start_handle The handle to begin the search at (generally the service definition handle). end_handle The handle to end the search at (generally the last handle in the service). cb The function to call to report procedure status updates; null for no callback. cb_arg The optional argument to pass to the callback function.","title":"Parameters"},{"location":"network/ble/ble_hs/ble_gattc/functions/ble_gattc_find_inc_svcs/#returned-values","text":"Value Condition 0 Success. Core return code Unexpected error.","title":"Returned values"},{"location":"network/ble/ble_hs/ble_gattc/functions/ble_gattc_indicate/","text":"ble_gattc_indicate int ble_gattc_indicate ( uint16_t conn_handle , uint16_t chr_val_handle ) Description Sends a characteristic indication. The content of the message is read from the specified characteristic. Parameters Parameter Description conn_handle The connection over which to execute the procedure. chr_val_handle The value attribute handle of the characteristic to include in the outgoing indication. Returned values Value Condition 0 Success. Core return code Unexpected error.","title":"ble_gattc_indicate"},{"location":"network/ble/ble_hs/ble_gattc/functions/ble_gattc_indicate/#ble_gattc_indicate","text":"int ble_gattc_indicate ( uint16_t conn_handle , uint16_t chr_val_handle )","title":"ble_gattc_indicate"},{"location":"network/ble/ble_hs/ble_gattc/functions/ble_gattc_indicate/#description","text":"Sends a characteristic indication. The content of the message is read from the specified characteristic.","title":"Description"},{"location":"network/ble/ble_hs/ble_gattc/functions/ble_gattc_indicate/#parameters","text":"Parameter Description conn_handle The connection over which to execute the procedure. chr_val_handle The value attribute handle of the characteristic to include in the outgoing indication.","title":"Parameters"},{"location":"network/ble/ble_hs/ble_gattc/functions/ble_gattc_indicate/#returned-values","text":"Value Condition 0 Success. Core return code Unexpected error.","title":"Returned values"},{"location":"network/ble/ble_hs/ble_gattc/functions/ble_gattc_notify/","text":"ble_gattc_notify int ble_gattc_notify ( uint16_t conn_handle , uint16_t chr_val_handle ) Description Sends a characteristic notification. The content of the message is read from the specified characteristic. Parameters Parameter Description conn_handle The connection over which to execute the procedure. chr_val_handle The value attribute handle of the characteristic to include in the outgoing notification. Returned values Value Condition 0 Success. Core return code Unexpected error.","title":"ble_gattc_notify"},{"location":"network/ble/ble_hs/ble_gattc/functions/ble_gattc_notify/#ble_gattc_notify","text":"int ble_gattc_notify ( uint16_t conn_handle , uint16_t chr_val_handle )","title":"ble_gattc_notify"},{"location":"network/ble/ble_hs/ble_gattc/functions/ble_gattc_notify/#description","text":"Sends a characteristic notification. The content of the message is read from the specified characteristic.","title":"Description"},{"location":"network/ble/ble_hs/ble_gattc/functions/ble_gattc_notify/#parameters","text":"Parameter Description conn_handle The connection over which to execute the procedure. chr_val_handle The value attribute handle of the characteristic to include in the outgoing notification.","title":"Parameters"},{"location":"network/ble/ble_hs/ble_gattc/functions/ble_gattc_notify/#returned-values","text":"Value Condition 0 Success. Core return code Unexpected error.","title":"Returned values"},{"location":"network/ble/ble_hs/ble_gattc/functions/ble_gattc_notify_custom/","text":"ble_gattc_notify_custom int ble_gattc_notify_custom ( uint16_t conn_handle , uint16_t chr_val_handle , struct os_mbuf *txom ) Description Sends a \"free-form\" characteristic notification. This function consumes the supplied mbuf regardless of the outcome. Parameters Parameter Description conn_handle The connection over which to execute the procedure. chr_val_handle The attribute handle to indicate in the outgoing notification. txom The value to write to the characteristic. Returned values Value Condition 0 Success. Core return code Unexpected error.","title":"ble_gattc_notify_custom"},{"location":"network/ble/ble_hs/ble_gattc/functions/ble_gattc_notify_custom/#ble_gattc_notify_custom","text":"int ble_gattc_notify_custom ( uint16_t conn_handle , uint16_t chr_val_handle , struct os_mbuf *txom )","title":"ble_gattc_notify_custom"},{"location":"network/ble/ble_hs/ble_gattc/functions/ble_gattc_notify_custom/#description","text":"Sends a \"free-form\" characteristic notification. This function consumes the supplied mbuf regardless of the outcome.","title":"Description"},{"location":"network/ble/ble_hs/ble_gattc/functions/ble_gattc_notify_custom/#parameters","text":"Parameter Description conn_handle The connection over which to execute the procedure. chr_val_handle The attribute handle to indicate in the outgoing notification. txom The value to write to the characteristic.","title":"Parameters"},{"location":"network/ble/ble_hs/ble_gattc/functions/ble_gattc_notify_custom/#returned-values","text":"Value Condition 0 Success. Core return code Unexpected error.","title":"Returned values"},{"location":"network/ble/ble_hs/ble_gattc/functions/ble_gattc_read/","text":"ble_gattc_read int ble_gattc_read ( uint16_t conn_handle , uint16_t attr_handle , ble_gatt_attr_fn *cb , void *cb_arg ) Description Initiates GATT procedure: Read Characteristic Value. Parameters Parameter Description conn_handle The connection over which to execute the procedure. attr_handle The handle of the characteristic value to read. cb The function to call to report procedure status updates; null for no callback. cb_arg The optional argument to pass to the callback function. Returned values Value Condition 0 Success. Core return code Unexpected error.","title":"ble_gattc_read"},{"location":"network/ble/ble_hs/ble_gattc/functions/ble_gattc_read/#ble_gattc_read","text":"int ble_gattc_read ( uint16_t conn_handle , uint16_t attr_handle , ble_gatt_attr_fn *cb , void *cb_arg )","title":"ble_gattc_read"},{"location":"network/ble/ble_hs/ble_gattc/functions/ble_gattc_read/#description","text":"Initiates GATT procedure: Read Characteristic Value.","title":"Description"},{"location":"network/ble/ble_hs/ble_gattc/functions/ble_gattc_read/#parameters","text":"Parameter Description conn_handle The connection over which to execute the procedure. attr_handle The handle of the characteristic value to read. cb The function to call to report procedure status updates; null for no callback. cb_arg The optional argument to pass to the callback function.","title":"Parameters"},{"location":"network/ble/ble_hs/ble_gattc/functions/ble_gattc_read/#returned-values","text":"Value Condition 0 Success. Core return code Unexpected error.","title":"Returned values"},{"location":"network/ble/ble_hs/ble_gattc/functions/ble_gattc_read_by_uuid/","text":"ble_gattc_read_by_uuid int ble_gattc_read_by_uuid ( uint16_t conn_handle , uint16_t start_handle , uint16_t end_handle , const void *uuid128 , ble_gatt_attr_fn *cb , void *cb_arg ) Description Initiates GATT procedure: Read Using Characteristic UUID. Parameters Parameter Description conn_handle The connection over which to execute the procedure. start_handle The first handle to search (generally the handle of the service definition). end_handle The last handle to search (generally the last handle in the service definition). cb The function to call to report procedure status updates; null for no callback. cb_arg The optional argument to pass to the callback function. Returned values Value Condition 0 Success. Core return code Unexpected error.","title":"ble_gattc_read_by_uuid"},{"location":"network/ble/ble_hs/ble_gattc/functions/ble_gattc_read_by_uuid/#ble_gattc_read_by_uuid","text":"int ble_gattc_read_by_uuid ( uint16_t conn_handle , uint16_t start_handle , uint16_t end_handle , const void *uuid128 , ble_gatt_attr_fn *cb , void *cb_arg )","title":"ble_gattc_read_by_uuid"},{"location":"network/ble/ble_hs/ble_gattc/functions/ble_gattc_read_by_uuid/#description","text":"Initiates GATT procedure: Read Using Characteristic UUID.","title":"Description"},{"location":"network/ble/ble_hs/ble_gattc/functions/ble_gattc_read_by_uuid/#parameters","text":"Parameter Description conn_handle The connection over which to execute the procedure. start_handle The first handle to search (generally the handle of the service definition). end_handle The last handle to search (generally the last handle in the service definition). cb The function to call to report procedure status updates; null for no callback. cb_arg The optional argument to pass to the callback function.","title":"Parameters"},{"location":"network/ble/ble_hs/ble_gattc/functions/ble_gattc_read_by_uuid/#returned-values","text":"Value Condition 0 Success. Core return code Unexpected error.","title":"Returned values"},{"location":"network/ble/ble_hs/ble_gattc/functions/ble_gattc_read_long/","text":"ble_gattc_read_long int ble_gattc_read_long ( uint16_t conn_handle , uint16_t handle , ble_gatt_attr_fn *cb , void *cb_arg ) Description Initiates GATT procedure: Read Long Characteristic Values. Parameters Parameter Description conn_handle The connection over which to execute the procedure. handle The handle of the characteristic value to read. cb The function to call to report procedure status updates; null for no callback. cb_arg The optional argument to pass to the callback function. Returned values Value Condition 0 Success. Core return code Unexpected error.","title":"ble_gattc_read_long"},{"location":"network/ble/ble_hs/ble_gattc/functions/ble_gattc_read_long/#ble_gattc_read_long","text":"int ble_gattc_read_long ( uint16_t conn_handle , uint16_t handle , ble_gatt_attr_fn *cb , void *cb_arg )","title":"ble_gattc_read_long"},{"location":"network/ble/ble_hs/ble_gattc/functions/ble_gattc_read_long/#description","text":"Initiates GATT procedure: Read Long Characteristic Values.","title":"Description"},{"location":"network/ble/ble_hs/ble_gattc/functions/ble_gattc_read_long/#parameters","text":"Parameter Description conn_handle The connection over which to execute the procedure. handle The handle of the characteristic value to read. cb The function to call to report procedure status updates; null for no callback. cb_arg The optional argument to pass to the callback function.","title":"Parameters"},{"location":"network/ble/ble_hs/ble_gattc/functions/ble_gattc_read_long/#returned-values","text":"Value Condition 0 Success. Core return code Unexpected error.","title":"Returned values"},{"location":"network/ble/ble_hs/ble_gattc/functions/ble_gattc_read_mult/","text":"ble_gattc_read_mult int ble_gattc_read_mult ( uint16_t conn_handle , const uint16_t *handles , uint8_t num_handles , ble_gatt_attr_fn *cb , void *cb_arg ) Description Initiates GATT procedure: Read Multiple Characteristic Values. Parameters Parameter Description conn_handle The connection over which to execute the procedure. handles An array of 16-bit attribute handles to read. num_handles The number of entries in the \"handles\" array. cb The function to call to report procedure status updates; null for no callback. cb_arg The optional argument to pass to the callback function. Returned values Value Condition 0 Success. Core return code Unexpected error.","title":"ble_gattc_read_mult"},{"location":"network/ble/ble_hs/ble_gattc/functions/ble_gattc_read_mult/#ble_gattc_read_mult","text":"int ble_gattc_read_mult ( uint16_t conn_handle , const uint16_t *handles , uint8_t num_handles , ble_gatt_attr_fn *cb , void *cb_arg )","title":"ble_gattc_read_mult"},{"location":"network/ble/ble_hs/ble_gattc/functions/ble_gattc_read_mult/#description","text":"Initiates GATT procedure: Read Multiple Characteristic Values.","title":"Description"},{"location":"network/ble/ble_hs/ble_gattc/functions/ble_gattc_read_mult/#parameters","text":"Parameter Description conn_handle The connection over which to execute the procedure. handles An array of 16-bit attribute handles to read. num_handles The number of entries in the \"handles\" array. cb The function to call to report procedure status updates; null for no callback. cb_arg The optional argument to pass to the callback function.","title":"Parameters"},{"location":"network/ble/ble_hs/ble_gattc/functions/ble_gattc_read_mult/#returned-values","text":"Value Condition 0 Success. Core return code Unexpected error.","title":"Returned values"},{"location":"network/ble/ble_hs/ble_gattc/functions/ble_gattc_write/","text":"ble_gattc_write int ble_gattc_write ( uint16_t conn_handle , uint16_t attr_handle , struct os_mbuf *txom , ble_gatt_attr_fn *cb , void *cb_arg ) Description Initiates GATT procedure: Write Characteristic Value. This function consumes the supplied mbuf regardless of the outcome. Parameters Parameter Description conn_handle The connection over which to execute the procedure. attr_handle The handle of the characteristic value to write to. txom The value to write to the characteristic. cb The function to call to report procedure status updates; null for no callback. cb_arg The optional argument to pass to the callback function. Returned values Value Condition 0 Success. Core return code Unexpected error.","title":"ble_gattc_write"},{"location":"network/ble/ble_hs/ble_gattc/functions/ble_gattc_write/#ble_gattc_write","text":"int ble_gattc_write ( uint16_t conn_handle , uint16_t attr_handle , struct os_mbuf *txom , ble_gatt_attr_fn *cb , void *cb_arg )","title":"ble_gattc_write"},{"location":"network/ble/ble_hs/ble_gattc/functions/ble_gattc_write/#description","text":"Initiates GATT procedure: Write Characteristic Value. This function consumes the supplied mbuf regardless of the outcome.","title":"Description"},{"location":"network/ble/ble_hs/ble_gattc/functions/ble_gattc_write/#parameters","text":"Parameter Description conn_handle The connection over which to execute the procedure. attr_handle The handle of the characteristic value to write to. txom The value to write to the characteristic. cb The function to call to report procedure status updates; null for no callback. cb_arg The optional argument to pass to the callback function.","title":"Parameters"},{"location":"network/ble/ble_hs/ble_gattc/functions/ble_gattc_write/#returned-values","text":"Value Condition 0 Success. Core return code Unexpected error.","title":"Returned values"},{"location":"network/ble/ble_hs/ble_gattc/functions/ble_gattc_write_flat/","text":"ble_gattc_write_flat int ble_gattc_write_flat ( uint16_t conn_handle , uint16_t attr_handle , const void *data , uint16_t data_len , ble_gatt_attr_fn *cb , void *cb_arg ) Description Initiates GATT procedure: Write Characteristic Value (flat buffer version). Parameters Parameter Description conn_handle The connection over which to execute the procedure. attr_handle The handle of the characteristic value to write to. value The value to write to the characteristic. value_len The number of bytes to write. cb The function to call to report procedure status updates; null for no callback. cb_arg The optional argument to pass to the callback function. Returned values Value Condition 0 Success. Core return code Unexpected error.","title":"ble_gattc_write_flat"},{"location":"network/ble/ble_hs/ble_gattc/functions/ble_gattc_write_flat/#ble_gattc_write_flat","text":"int ble_gattc_write_flat ( uint16_t conn_handle , uint16_t attr_handle , const void *data , uint16_t data_len , ble_gatt_attr_fn *cb , void *cb_arg )","title":"ble_gattc_write_flat"},{"location":"network/ble/ble_hs/ble_gattc/functions/ble_gattc_write_flat/#description","text":"Initiates GATT procedure: Write Characteristic Value (flat buffer version).","title":"Description"},{"location":"network/ble/ble_hs/ble_gattc/functions/ble_gattc_write_flat/#parameters","text":"Parameter Description conn_handle The connection over which to execute the procedure. attr_handle The handle of the characteristic value to write to. value The value to write to the characteristic. value_len The number of bytes to write. cb The function to call to report procedure status updates; null for no callback. cb_arg The optional argument to pass to the callback function.","title":"Parameters"},{"location":"network/ble/ble_hs/ble_gattc/functions/ble_gattc_write_flat/#returned-values","text":"Value Condition 0 Success. Core return code Unexpected error.","title":"Returned values"},{"location":"network/ble/ble_hs/ble_gattc/functions/ble_gattc_write_long/","text":"ble_gattc_write_long int ble_gattc_write_long ( uint16_t conn_handle , uint16_t attr_handle , struct os_mbuf *txom , ble_gatt_attr_fn *cb , void *cb_arg ) Description Initiates GATT procedure: Write Long Characteristic Values. This function consumes the supplied mbuf regardless of the outcome. Parameters Parameter Description conn_handle The connection over which to execute the procedure. attr_handle The handle of the characteristic value to write to. txom The value to write to the characteristic. cb The function to call to report procedure status updates; null for no callback. cb_arg The optional argument to pass to the callback function. Returned values Value Condition 0 Success. Core return code Unexpected error.","title":"ble_gattc_write_long"},{"location":"network/ble/ble_hs/ble_gattc/functions/ble_gattc_write_long/#ble_gattc_write_long","text":"int ble_gattc_write_long ( uint16_t conn_handle , uint16_t attr_handle , struct os_mbuf *txom , ble_gatt_attr_fn *cb , void *cb_arg )","title":"ble_gattc_write_long"},{"location":"network/ble/ble_hs/ble_gattc/functions/ble_gattc_write_long/#description","text":"Initiates GATT procedure: Write Long Characteristic Values. This function consumes the supplied mbuf regardless of the outcome.","title":"Description"},{"location":"network/ble/ble_hs/ble_gattc/functions/ble_gattc_write_long/#parameters","text":"Parameter Description conn_handle The connection over which to execute the procedure. attr_handle The handle of the characteristic value to write to. txom The value to write to the characteristic. cb The function to call to report procedure status updates; null for no callback. cb_arg The optional argument to pass to the callback function.","title":"Parameters"},{"location":"network/ble/ble_hs/ble_gattc/functions/ble_gattc_write_long/#returned-values","text":"Value Condition 0 Success. Core return code Unexpected error.","title":"Returned values"},{"location":"network/ble/ble_hs/ble_gattc/functions/ble_gattc_write_no_rsp/","text":"ble_gattc_write_no_rsp int ble_gattc_write_no_rsp ( uint16_t conn_handle , uint16_t attr_handle , struct os_mbuf *txom ) Description Initiates GATT procedure: Write Without Response. This function consumes the supplied mbuf regardless of the outcome. Parameters Parameter Description conn_handle The connection over which to execute the procedure. attr_handle The handle of the characteristic value to write to. txom The value to write to the characteristic. Returned values Value Condition 0 Success. Core return code Unexpected error.","title":"ble_gattc_write_no_rsp"},{"location":"network/ble/ble_hs/ble_gattc/functions/ble_gattc_write_no_rsp/#ble_gattc_write_no_rsp","text":"int ble_gattc_write_no_rsp ( uint16_t conn_handle , uint16_t attr_handle , struct os_mbuf *txom )","title":"ble_gattc_write_no_rsp"},{"location":"network/ble/ble_hs/ble_gattc/functions/ble_gattc_write_no_rsp/#description","text":"Initiates GATT procedure: Write Without Response. This function consumes the supplied mbuf regardless of the outcome.","title":"Description"},{"location":"network/ble/ble_hs/ble_gattc/functions/ble_gattc_write_no_rsp/#parameters","text":"Parameter Description conn_handle The connection over which to execute the procedure. attr_handle The handle of the characteristic value to write to. txom The value to write to the characteristic.","title":"Parameters"},{"location":"network/ble/ble_hs/ble_gattc/functions/ble_gattc_write_no_rsp/#returned-values","text":"Value Condition 0 Success. Core return code Unexpected error.","title":"Returned values"},{"location":"network/ble/ble_hs/ble_gattc/functions/ble_gattc_write_no_rsp_flat/","text":"ble_gattc_write_no_rsp_flat int ble_gattc_write_no_rsp_flat ( uint16_t conn_handle , uint16_t attr_handle , const void *data , uint16_t data_len ) Description Initiates GATT procedure: Write Without Response. This function consumes the supplied mbuf regardless of the outcome. Parameters Parameter Description conn_handle The connection over which to execute the procedure. attr_handle The handle of the characteristic value to write to. value The value to write to the characteristic. value_len The number of bytes to write. Returned values Value Condition 0 Success. Core return code Unexpected error.","title":"ble_gattc_write_no_rsp_flat"},{"location":"network/ble/ble_hs/ble_gattc/functions/ble_gattc_write_no_rsp_flat/#ble_gattc_write_no_rsp_flat","text":"int ble_gattc_write_no_rsp_flat ( uint16_t conn_handle , uint16_t attr_handle , const void *data , uint16_t data_len )","title":"ble_gattc_write_no_rsp_flat"},{"location":"network/ble/ble_hs/ble_gattc/functions/ble_gattc_write_no_rsp_flat/#description","text":"Initiates GATT procedure: Write Without Response. This function consumes the supplied mbuf regardless of the outcome.","title":"Description"},{"location":"network/ble/ble_hs/ble_gattc/functions/ble_gattc_write_no_rsp_flat/#parameters","text":"Parameter Description conn_handle The connection over which to execute the procedure. attr_handle The handle of the characteristic value to write to. value The value to write to the characteristic. value_len The number of bytes to write.","title":"Parameters"},{"location":"network/ble/ble_hs/ble_gattc/functions/ble_gattc_write_no_rsp_flat/#returned-values","text":"Value Condition 0 Success. Core return code Unexpected error.","title":"Returned values"},{"location":"network/ble/ble_hs/ble_gattc/functions/ble_gattc_write_reliable/","text":"ble_gattc_write_reliable int ble_gattc_write_reliable ( uint16_t conn_handle , struct ble_gatt_attr *attrs , int num_attrs , ble_gatt_reliable_attr_fn *cb , void *cb_arg ) Description Initiates GATT procedure: Reliable Writes. This function consumes the supplied mbufs regardless of the outcome. Parameters Parameter Description conn_handle The connection over which to execute the procedure. attrs An array of attribute descriptors; specifies which characteristics to write to and what data to write to them. The mbuf pointer in each attribute is set to NULL by this function. num_attrs The number of characteristics to write; equal to the number of elements in the 'attrs' array. cb The function to call to report procedure status updates; null for no callback. cb_arg The optional argument to pass to the callback function. Returned values None","title":"ble_gattc_write_reliable"},{"location":"network/ble/ble_hs/ble_gattc/functions/ble_gattc_write_reliable/#ble_gattc_write_reliable","text":"int ble_gattc_write_reliable ( uint16_t conn_handle , struct ble_gatt_attr *attrs , int num_attrs , ble_gatt_reliable_attr_fn *cb , void *cb_arg )","title":"ble_gattc_write_reliable"},{"location":"network/ble/ble_hs/ble_gattc/functions/ble_gattc_write_reliable/#description","text":"Initiates GATT procedure: Reliable Writes. This function consumes the supplied mbufs regardless of the outcome.","title":"Description"},{"location":"network/ble/ble_hs/ble_gattc/functions/ble_gattc_write_reliable/#parameters","text":"Parameter Description conn_handle The connection over which to execute the procedure. attrs An array of attribute descriptors; specifies which characteristics to write to and what data to write to them. The mbuf pointer in each attribute is set to NULL by this function. num_attrs The number of characteristics to write; equal to the number of elements in the 'attrs' array. cb The function to call to report procedure status updates; null for no callback. cb_arg The optional argument to pass to the callback function.","title":"Parameters"},{"location":"network/ble/ble_hs/ble_gattc/functions/ble_gattc_write_reliable/#returned-values","text":"None","title":"Returned values"},{"location":"network/ble/ble_hs/ble_gatts/ble_gatts/","text":"NimBLE Host GATT Server Reference Introduction The Generic Attribute Profile (GATT) manages all activities involving services, characteristics, and descriptors. The server half of the GATT API handles registration and responding to GATT clients. Header #include \"host/ble_hs.h\" Definitions BLE host GATT server definitions Functions Function Description ble_gatts_add_svcs Queues a set of service definitions for registration. ble_gatts_count_cfg Adjusts a host configuration object's settings to accommodate the specified service definition array. ble_gatts_count_resources Accumulates counts of each resource type required by the specified service definition array. ble_gatts_find_chr Retrieves the pair of attribute handles associated with a local GATT characteristic. ble_gatts_find_dsc Retrieves the attribute handle associated with a local GATT descriptor. ble_gatts_find_svc Retrieves the attribute handle associated with a local GATT service. ble_gatts_register_svcs Registers a set of services, characteristics, and descriptors to be accessed by GATT clients.","title":"toc"},{"location":"network/ble/ble_hs/ble_gatts/ble_gatts/#nimble-host-gatt-server-reference","text":"","title":"NimBLE Host GATT Server Reference"},{"location":"network/ble/ble_hs/ble_gatts/ble_gatts/#introduction","text":"The Generic Attribute Profile (GATT) manages all activities involving services, characteristics, and descriptors. The server half of the GATT API handles registration and responding to GATT clients.","title":"Introduction"},{"location":"network/ble/ble_hs/ble_gatts/ble_gatts/#header","text":"#include \"host/ble_hs.h\"","title":"Header"},{"location":"network/ble/ble_hs/ble_gatts/ble_gatts/#definitions","text":"BLE host GATT server definitions","title":"Definitions"},{"location":"network/ble/ble_hs/ble_gatts/ble_gatts/#functions","text":"Function Description ble_gatts_add_svcs Queues a set of service definitions for registration. ble_gatts_count_cfg Adjusts a host configuration object's settings to accommodate the specified service definition array. ble_gatts_count_resources Accumulates counts of each resource type required by the specified service definition array. ble_gatts_find_chr Retrieves the pair of attribute handles associated with a local GATT characteristic. ble_gatts_find_dsc Retrieves the attribute handle associated with a local GATT descriptor. ble_gatts_find_svc Retrieves the attribute handle associated with a local GATT service. ble_gatts_register_svcs Registers a set of services, characteristics, and descriptors to be accessed by GATT clients.","title":"Functions"},{"location":"network/ble/ble_hs/ble_gatts/definitions/ble_gatts_defs/","text":"GATT Server Definitions typedef int ble_gatt_access_fn ( uint16_t conn_handle , uint16_t attr_handle , struct ble_gatt_access_ctxt *ctxt , void *arg ); typedef uint16_t ble_gatt_chr_flags ; struct ble_gatt_chr_def { /** * Pointer to first element in a uint8_t[16]; use the BLE_UUID16 macro for * 16-bit UUIDs; NULL if there are no more characteristics in the service. */ const uint8_t *uuid128 ; /** * Callback that gets executed when this characteristic is read or * written. */ ble_gatt_access_fn *access_cb ; /** Optional argument for callback. */ void *arg ; /** * Array of this characteristic's descriptors. NULL if no descriptors. * Do not include CCCD; it gets added automatically if this * characteristic's notify or indicate flag is set. */ struct ble_gatt_dsc_def *descriptors ; /** Specifies the set of permitted operations for this characteristic. */ ble_gatt_chr_flags flags ; /** * At registration time, this is filled in with the characteristic's value * attribute handle. */ uint16_t * const val_handle ; }; struct ble_gatt_svc_def { /** * One of the following: * o BLE_GATT_SVC_TYPE_PRIMARY - primary service * o BLE_GATT_SVC_TYPE_SECONDARY - secondary service * o 0 - No more services in this array. */ uint8_t type ; /** * Pointer to first element in a uint8_t[16]; use the BLE_UUID16 macro for * 16-bit UUIDs. */ const uint8_t *uuid128 ; /** * Array of pointers to other service definitions. These services are * reported as \"included services\" during service discovery. Terminate the * array with NULL. */ const struct ble_gatt_svc_def **includes ; /** * Array of characteristic definitions corresponding to characteristics * belonging to this service. */ const struct ble_gatt_chr_def *characteristics ; }; struct ble_gatt_dsc_def { /** * The first element in a uint8_t[16]; use the BLE_UUID16 macro for 16-bit * UUIDs; NULL if there are no more descriptors in the characteristic. */ uint8_t *uuid128 ; /** Specifies the set of permitted operations for this descriptor. */ uint8_t att_flags ; /** Callback that gets executed when the descriptor is read or written. */ ble_gatt_access_fn *access_cb ; /** Optional argument for callback. */ void *arg ; }; /** * Context for an access to a GATT characteristic or descriptor. When a client * reads or writes a locally registered characteristic or descriptor, an * instance of this struct gets passed to the application callback. */ struct ble_gatt_access_ctxt { /** * Indicates the gatt operation being performed. This is equal to one of * the following values: * o BLE_GATT_ACCESS_OP_READ_CHR * o BLE_GATT_ACCESS_OP_WRITE_CHR * o BLE_GATT_ACCESS_OP_READ_DSC * o BLE_GATT_ACCESS_OP_WRITE_DSC */ uint8_t op ; /** * A container for the GATT access data. * o For reads: The application populates this with the value of the * characteristic or descriptor being read. * o For writes: This is already populated with the value being written * by the peer. If the application wishes to retain this mbuf for * later use, the access callback must set this pointer to NULL to * prevent the stack from freeing it. */ struct os_mbuf *om ; /** * The GATT operation being performed dictates which field in this union is * valid. If a characteristic is being accessed, the chr field is valid. * Otherwise a descriptor is being accessed, in which case the dsc field * is valid. */ union { /** * The characteristic definition corresponding to the characteristic * being accessed. This is what the app registered at startup. */ const struct ble_gatt_chr_def *chr ; /** * The descriptor definition corresponding to the descriptor being * accessed. This is what the app registered at startup. */ const struct ble_gatt_dsc_def *dsc ; }; }; /** * Context passed to the registration callback; represents the GATT service, * characteristic, or descriptor being registered. */ union ble_gatt_register_ctxt { /** Service; valid if op == BLE_GATT_REGISTER_OP_SVC. */ struct { /** The ATT handle of the service definition attribute. */ uint16_t handle ; /** * The service definition representing the service being * registered. */ const struct ble_gatt_svc_def *svc_def ; } svc ; /** Characteristic; valid if op == BLE_GATT_REGISTER_OP_CHR. */ struct { /** The ATT handle of the characteristic definition attribute. */ uint16_t def_handle ; /** The ATT handle of the characteristic value attribute. */ uint16_t val_handle ; /** * The characteristic definition representing the characteristic being * registered. */ const struct ble_gatt_chr_def *chr_def ; /** * The service definition corresponding to the characteristic's parent * service. */ const struct ble_gatt_svc_def *svc_def ; } chr ; /** Descriptor; valid if op == BLE_GATT_REGISTER_OP_DSC. */ struct { /** The ATT handle of the descriptor definition attribute. */ uint16_t handle ; /** * The descriptor definition corresponding to the descriptor being * registered. */ const struct ble_gatt_dsc_def *dsc_def ; /** * The characteristic definition corresponding to the descriptor's * parent characteristic. */ const struct ble_gatt_chr_def *chr_def ; /** * The service definition corresponding to the descriptor's grandparent * service */ const struct ble_gatt_svc_def *svc_def ; } dsc ; }; typedef void ble_gatt_register_fn ( uint8_t op , union ble_gatt_register_ctxt *ctxt , void *arg ); /** * Contains counts of resources required by the GATT server. The contents of * this struct are generally used to populate a configuration struct before * the host is initialized. */ struct ble_gatt_resources { /** Number of services. */ uint16_t svcs ; /** Number of included services. */ uint16_t incs ; /** Number of characteristics. */ uint16_t chrs ; /** Number of descriptors. */ uint16_t dscs ; /** * Number of client characteristic configuration descriptors. Each of * these also contributes to the total descriptor count. */ uint16_t cccds ; /** Total number of ATT attributes. */ uint16_t attrs ; };","title":"GATT server definitions"},{"location":"network/ble/ble_hs/ble_gatts/definitions/ble_gatts_defs/#gatt-server-definitions","text":"typedef int ble_gatt_access_fn ( uint16_t conn_handle , uint16_t attr_handle , struct ble_gatt_access_ctxt *ctxt , void *arg ); typedef uint16_t ble_gatt_chr_flags ; struct ble_gatt_chr_def { /** * Pointer to first element in a uint8_t[16]; use the BLE_UUID16 macro for * 16-bit UUIDs; NULL if there are no more characteristics in the service. */ const uint8_t *uuid128 ; /** * Callback that gets executed when this characteristic is read or * written. */ ble_gatt_access_fn *access_cb ; /** Optional argument for callback. */ void *arg ; /** * Array of this characteristic's descriptors. NULL if no descriptors. * Do not include CCCD; it gets added automatically if this * characteristic's notify or indicate flag is set. */ struct ble_gatt_dsc_def *descriptors ; /** Specifies the set of permitted operations for this characteristic. */ ble_gatt_chr_flags flags ; /** * At registration time, this is filled in with the characteristic's value * attribute handle. */ uint16_t * const val_handle ; }; struct ble_gatt_svc_def { /** * One of the following: * o BLE_GATT_SVC_TYPE_PRIMARY - primary service * o BLE_GATT_SVC_TYPE_SECONDARY - secondary service * o 0 - No more services in this array. */ uint8_t type ; /** * Pointer to first element in a uint8_t[16]; use the BLE_UUID16 macro for * 16-bit UUIDs. */ const uint8_t *uuid128 ; /** * Array of pointers to other service definitions. These services are * reported as \"included services\" during service discovery. Terminate the * array with NULL. */ const struct ble_gatt_svc_def **includes ; /** * Array of characteristic definitions corresponding to characteristics * belonging to this service. */ const struct ble_gatt_chr_def *characteristics ; }; struct ble_gatt_dsc_def { /** * The first element in a uint8_t[16]; use the BLE_UUID16 macro for 16-bit * UUIDs; NULL if there are no more descriptors in the characteristic. */ uint8_t *uuid128 ; /** Specifies the set of permitted operations for this descriptor. */ uint8_t att_flags ; /** Callback that gets executed when the descriptor is read or written. */ ble_gatt_access_fn *access_cb ; /** Optional argument for callback. */ void *arg ; }; /** * Context for an access to a GATT characteristic or descriptor. When a client * reads or writes a locally registered characteristic or descriptor, an * instance of this struct gets passed to the application callback. */ struct ble_gatt_access_ctxt { /** * Indicates the gatt operation being performed. This is equal to one of * the following values: * o BLE_GATT_ACCESS_OP_READ_CHR * o BLE_GATT_ACCESS_OP_WRITE_CHR * o BLE_GATT_ACCESS_OP_READ_DSC * o BLE_GATT_ACCESS_OP_WRITE_DSC */ uint8_t op ; /** * A container for the GATT access data. * o For reads: The application populates this with the value of the * characteristic or descriptor being read. * o For writes: This is already populated with the value being written * by the peer. If the application wishes to retain this mbuf for * later use, the access callback must set this pointer to NULL to * prevent the stack from freeing it. */ struct os_mbuf *om ; /** * The GATT operation being performed dictates which field in this union is * valid. If a characteristic is being accessed, the chr field is valid. * Otherwise a descriptor is being accessed, in which case the dsc field * is valid. */ union { /** * The characteristic definition corresponding to the characteristic * being accessed. This is what the app registered at startup. */ const struct ble_gatt_chr_def *chr ; /** * The descriptor definition corresponding to the descriptor being * accessed. This is what the app registered at startup. */ const struct ble_gatt_dsc_def *dsc ; }; }; /** * Context passed to the registration callback; represents the GATT service, * characteristic, or descriptor being registered. */ union ble_gatt_register_ctxt { /** Service; valid if op == BLE_GATT_REGISTER_OP_SVC. */ struct { /** The ATT handle of the service definition attribute. */ uint16_t handle ; /** * The service definition representing the service being * registered. */ const struct ble_gatt_svc_def *svc_def ; } svc ; /** Characteristic; valid if op == BLE_GATT_REGISTER_OP_CHR. */ struct { /** The ATT handle of the characteristic definition attribute. */ uint16_t def_handle ; /** The ATT handle of the characteristic value attribute. */ uint16_t val_handle ; /** * The characteristic definition representing the characteristic being * registered. */ const struct ble_gatt_chr_def *chr_def ; /** * The service definition corresponding to the characteristic's parent * service. */ const struct ble_gatt_svc_def *svc_def ; } chr ; /** Descriptor; valid if op == BLE_GATT_REGISTER_OP_DSC. */ struct { /** The ATT handle of the descriptor definition attribute. */ uint16_t handle ; /** * The descriptor definition corresponding to the descriptor being * registered. */ const struct ble_gatt_dsc_def *dsc_def ; /** * The characteristic definition corresponding to the descriptor's * parent characteristic. */ const struct ble_gatt_chr_def *chr_def ; /** * The service definition corresponding to the descriptor's grandparent * service */ const struct ble_gatt_svc_def *svc_def ; } dsc ; }; typedef void ble_gatt_register_fn ( uint8_t op , union ble_gatt_register_ctxt *ctxt , void *arg ); /** * Contains counts of resources required by the GATT server. The contents of * this struct are generally used to populate a configuration struct before * the host is initialized. */ struct ble_gatt_resources { /** Number of services. */ uint16_t svcs ; /** Number of included services. */ uint16_t incs ; /** Number of characteristics. */ uint16_t chrs ; /** Number of descriptors. */ uint16_t dscs ; /** * Number of client characteristic configuration descriptors. Each of * these also contributes to the total descriptor count. */ uint16_t cccds ; /** Total number of ATT attributes. */ uint16_t attrs ; };","title":"GATT Server Definitions"},{"location":"network/ble/ble_hs/ble_gatts/functions/ble_gatts_add_svcs/","text":"ble_gatts_add_svcs int ble_gatts_add_svcs ( const struct ble_gatt_svc_def *svcs ) Description Queues a set of service definitions for registration. All services queued in this manner get registered when ble_hs_init() is called. Parameters Parameter Description svcs An array of service definitions to queue for registration. This array must be terminated with an entry whose 'type' equals 0. Returned values Value Condition 0 Success. BLE_HS_ENOMEM Heap exhaustion.","title":"ble_gatts_add_svcs"},{"location":"network/ble/ble_hs/ble_gatts/functions/ble_gatts_add_svcs/#ble_gatts_add_svcs","text":"int ble_gatts_add_svcs ( const struct ble_gatt_svc_def *svcs )","title":"ble_gatts_add_svcs"},{"location":"network/ble/ble_hs/ble_gatts/functions/ble_gatts_add_svcs/#description","text":"Queues a set of service definitions for registration. All services queued in this manner get registered when ble_hs_init() is called.","title":"Description"},{"location":"network/ble/ble_hs/ble_gatts/functions/ble_gatts_add_svcs/#parameters","text":"Parameter Description svcs An array of service definitions to queue for registration. This array must be terminated with an entry whose 'type' equals 0.","title":"Parameters"},{"location":"network/ble/ble_hs/ble_gatts/functions/ble_gatts_add_svcs/#returned-values","text":"Value Condition 0 Success. BLE_HS_ENOMEM Heap exhaustion.","title":"Returned values"},{"location":"network/ble/ble_hs/ble_gatts/functions/ble_gatts_count_cfg/","text":"ble_gatts_count_cfg int ble_gatts_count_cfg ( const struct ble_gatt_svc_def *defs , struct ble_hs_cfg *cfg ) Description Adjusts a host configuration object's settings to accommodate the specified service definition array. This function adds the counts to the appropriate fields in the supplied configuration object without clearing them first, so it can be called repeatedly with different inputs to calculate totals. Be sure to zero the GATT server settings prior to the first call to this function. Parameters Parameter Description defs The service array containing the resource definitions to be counted. cfg The resource counts are accumulated in this configuration object. Returned values Value Condition 0 Success. BLE_HS_EINVAL The svcs array contains an invalid resource definition.","title":"ble_gatts_count_cfg"},{"location":"network/ble/ble_hs/ble_gatts/functions/ble_gatts_count_cfg/#ble_gatts_count_cfg","text":"int ble_gatts_count_cfg ( const struct ble_gatt_svc_def *defs , struct ble_hs_cfg *cfg )","title":"ble_gatts_count_cfg"},{"location":"network/ble/ble_hs/ble_gatts/functions/ble_gatts_count_cfg/#description","text":"Adjusts a host configuration object's settings to accommodate the specified service definition array. This function adds the counts to the appropriate fields in the supplied configuration object without clearing them first, so it can be called repeatedly with different inputs to calculate totals. Be sure to zero the GATT server settings prior to the first call to this function.","title":"Description"},{"location":"network/ble/ble_hs/ble_gatts/functions/ble_gatts_count_cfg/#parameters","text":"Parameter Description defs The service array containing the resource definitions to be counted. cfg The resource counts are accumulated in this configuration object.","title":"Parameters"},{"location":"network/ble/ble_hs/ble_gatts/functions/ble_gatts_count_cfg/#returned-values","text":"Value Condition 0 Success. BLE_HS_EINVAL The svcs array contains an invalid resource definition.","title":"Returned values"},{"location":"network/ble/ble_hs/ble_gatts/functions/ble_gatts_count_resources/","text":"ble_gatts_count_resources int ble_gatts_count_resources ( const struct ble_gatt_svc_def *svcs , struct ble_gatt_resources *res ) Description Accumulates counts of each resource type required by the specified service definition array. This function is generally used to calculate some host configuration values prior to initialization. This function adds the counts to the appropriate fields in the supplied ble_gatt_resources object without clearing them first, so it can be called repeatedly with different inputs to calculate totals. Be sure to zero the resource struct prior to the first call to this function. Parameters Parameter Description svcs The service array containing the resource definitions to be counted. res The resource counts are accumulated in this struct. Returned values Value Condition 0 Success. BLE_HS_EINVAL The svcs array contains an invalid resource definition.","title":"ble_gatts_count_resources"},{"location":"network/ble/ble_hs/ble_gatts/functions/ble_gatts_count_resources/#ble_gatts_count_resources","text":"int ble_gatts_count_resources ( const struct ble_gatt_svc_def *svcs , struct ble_gatt_resources *res )","title":"ble_gatts_count_resources"},{"location":"network/ble/ble_hs/ble_gatts/functions/ble_gatts_count_resources/#description","text":"Accumulates counts of each resource type required by the specified service definition array. This function is generally used to calculate some host configuration values prior to initialization. This function adds the counts to the appropriate fields in the supplied ble_gatt_resources object without clearing them first, so it can be called repeatedly with different inputs to calculate totals. Be sure to zero the resource struct prior to the first call to this function.","title":"Description"},{"location":"network/ble/ble_hs/ble_gatts/functions/ble_gatts_count_resources/#parameters","text":"Parameter Description svcs The service array containing the resource definitions to be counted. res The resource counts are accumulated in this struct.","title":"Parameters"},{"location":"network/ble/ble_hs/ble_gatts/functions/ble_gatts_count_resources/#returned-values","text":"Value Condition 0 Success. BLE_HS_EINVAL The svcs array contains an invalid resource definition.","title":"Returned values"},{"location":"network/ble/ble_hs/ble_gatts/functions/ble_gatts_find_chr/","text":"ble_gatts_find_chr int ble_gatts_find_chr ( const void *svc_uuid128 , const void *chr_uuid128 , uint16_t *out_def_handle , uint16_t *out_val_handle ) Description Retrieves the pair of attribute handles associated with a local GATT characteristic. Parameters Parameter Description svc_uuid128 The UUID of the parent service. chr_uuid128 The UUID of the characteristic to look up. out_def_handle On success, populated with the handle of the characteristic definition attribute. Pass null if you don't need this value. out_val_handle On success, populated with the handle of the characteristic value attribute. Pass null if you don't need this value. Returned values Value Condition 0 Success. BLE_HS_ENOENT The specified service or characteristic could not be found.","title":"ble_gatts_find_chr"},{"location":"network/ble/ble_hs/ble_gatts/functions/ble_gatts_find_chr/#ble_gatts_find_chr","text":"int ble_gatts_find_chr ( const void *svc_uuid128 , const void *chr_uuid128 , uint16_t *out_def_handle , uint16_t *out_val_handle )","title":"ble_gatts_find_chr"},{"location":"network/ble/ble_hs/ble_gatts/functions/ble_gatts_find_chr/#description","text":"Retrieves the pair of attribute handles associated with a local GATT characteristic.","title":"Description"},{"location":"network/ble/ble_hs/ble_gatts/functions/ble_gatts_find_chr/#parameters","text":"Parameter Description svc_uuid128 The UUID of the parent service. chr_uuid128 The UUID of the characteristic to look up. out_def_handle On success, populated with the handle of the characteristic definition attribute. Pass null if you don't need this value. out_val_handle On success, populated with the handle of the characteristic value attribute. Pass null if you don't need this value.","title":"Parameters"},{"location":"network/ble/ble_hs/ble_gatts/functions/ble_gatts_find_chr/#returned-values","text":"Value Condition 0 Success. BLE_HS_ENOENT The specified service or characteristic could not be found.","title":"Returned values"},{"location":"network/ble/ble_hs/ble_gatts/functions/ble_gatts_find_dsc/","text":"ble_gatts_find_dsc int ble_gatts_find_dsc ( const void *svc_uuid128 , const void *chr_uuid128 , const void *dsc_uuid128 , uint16_t *out_handle ) Description Retrieves the attribute handle associated with a local GATT descriptor. Parameters Parameter Description svc_uuid128 The UUID of the grandparent service. chr_uuid128 The UUID of the parent characteristic. dsc_uuid128 The UUID of the descriptor ro look up. out_handle On success, populated with the handle of the descripytor attribute. Pass null if you don't need this value. Returned values Value Condition 0 Success. BLE_HS_ENOENT The specified service, characteristic, or descriptor could not be found.","title":"ble_gatts_find_dsc"},{"location":"network/ble/ble_hs/ble_gatts/functions/ble_gatts_find_dsc/#ble_gatts_find_dsc","text":"int ble_gatts_find_dsc ( const void *svc_uuid128 , const void *chr_uuid128 , const void *dsc_uuid128 , uint16_t *out_handle )","title":"ble_gatts_find_dsc"},{"location":"network/ble/ble_hs/ble_gatts/functions/ble_gatts_find_dsc/#description","text":"Retrieves the attribute handle associated with a local GATT descriptor.","title":"Description"},{"location":"network/ble/ble_hs/ble_gatts/functions/ble_gatts_find_dsc/#parameters","text":"Parameter Description svc_uuid128 The UUID of the grandparent service. chr_uuid128 The UUID of the parent characteristic. dsc_uuid128 The UUID of the descriptor ro look up. out_handle On success, populated with the handle of the descripytor attribute. Pass null if you don't need this value.","title":"Parameters"},{"location":"network/ble/ble_hs/ble_gatts/functions/ble_gatts_find_dsc/#returned-values","text":"Value Condition 0 Success. BLE_HS_ENOENT The specified service, characteristic, or descriptor could not be found.","title":"Returned values"},{"location":"network/ble/ble_hs/ble_gatts/functions/ble_gatts_find_svc/","text":"ble_gatts_find_svc int ble_gatts_find_svc ( const void *uuid128 , uint16_t *out_handle ) Description Retrieves the attribute handle associated with a local GATT service. Parameters Parameter Description uuid128 The UUID of the service to look up. out_handle On success, populated with the handle of the service attribute. Pass null if you don't need this value. Returned values Value Condition 0 Success. BLE_HS_ENOENT The specified service could not be found.","title":"ble_gatts_find_svc"},{"location":"network/ble/ble_hs/ble_gatts/functions/ble_gatts_find_svc/#ble_gatts_find_svc","text":"int ble_gatts_find_svc ( const void *uuid128 , uint16_t *out_handle )","title":"ble_gatts_find_svc"},{"location":"network/ble/ble_hs/ble_gatts/functions/ble_gatts_find_svc/#description","text":"Retrieves the attribute handle associated with a local GATT service.","title":"Description"},{"location":"network/ble/ble_hs/ble_gatts/functions/ble_gatts_find_svc/#parameters","text":"Parameter Description uuid128 The UUID of the service to look up. out_handle On success, populated with the handle of the service attribute. Pass null if you don't need this value.","title":"Parameters"},{"location":"network/ble/ble_hs/ble_gatts/functions/ble_gatts_find_svc/#returned-values","text":"Value Condition 0 Success. BLE_HS_ENOENT The specified service could not be found.","title":"Returned values"},{"location":"network/ble/ble_hs/ble_gatts/functions/ble_gatts_register_svcs/","text":"ble_gatts_register_svcs int ble_gatts_register_svcs ( const struct ble_gatt_svc_def *svcs , ble_gatt_register_fn *cb , void *cb_arg ) Description Registers a set of services, characteristics, and descriptors to be accessed by GATT clients. Parameters Parameter Description svcs A table of the service definitions to be registered. cb The function to call for each service, characteristic, and descriptor that gets registered. cb_arg The optional argument to pass to the callback function. Returned values Value Condition 0 Success. BLE_HS_ENOMEM Registration failed due to resource exhaustion. BLE_HS_EINVAL The service definition table contains an invalid element.","title":"ble_gatts_register_svcs"},{"location":"network/ble/ble_hs/ble_gatts/functions/ble_gatts_register_svcs/#ble_gatts_register_svcs","text":"int ble_gatts_register_svcs ( const struct ble_gatt_svc_def *svcs , ble_gatt_register_fn *cb , void *cb_arg )","title":"ble_gatts_register_svcs"},{"location":"network/ble/ble_hs/ble_gatts/functions/ble_gatts_register_svcs/#description","text":"Registers a set of services, characteristics, and descriptors to be accessed by GATT clients.","title":"Description"},{"location":"network/ble/ble_hs/ble_gatts/functions/ble_gatts_register_svcs/#parameters","text":"Parameter Description svcs A table of the service definitions to be registered. cb The function to call for each service, characteristic, and descriptor that gets registered. cb_arg The optional argument to pass to the callback function.","title":"Parameters"},{"location":"network/ble/ble_hs/ble_gatts/functions/ble_gatts_register_svcs/#returned-values","text":"Value Condition 0 Success. BLE_HS_ENOMEM Registration failed due to resource exhaustion. BLE_HS_EINVAL The service definition table contains an invalid element.","title":"Returned values"},{"location":"network/ble/ble_hs/ble_hs_id/ble_hs_id/","text":"NimBLE Host Identity Reference Introduction The identity API provides facilities for querying and configuring your device's addresses. BLE's addressing scheme is quite involved; the summary that follows is only a brief introduction. BLE defines four address types: Type Description Identity? Configured with Public Address assigned by manufacturer; the three most significant bytes form the manufacturer's OUI. Yes N/A; read from controller at startup. Static random Randomly generated address. Yes ble_hs_id_set_rnd() Resolvable private (RPA) Address randomly generated from an identity address and an identity resolving key (IRK). No N/A; generated by controller periodically. Non-resolvable private (NRPA) Randomly generated address. No ble_hs_id_set_rnd() Identity Addresses The third column in the above table indicates the identity property of each address type. An identity address never changes, and a device can be identified by one of its unique identity addresses. Non-identity addresses are used by devices supporting BLE privacy. A device using the privacy feature frequently changes its own address to a newly-generated non-identity address. By cycling its address, the device makes it impossible for eavesdroppers to track its location. A device can have up to two identity addresses at once: one public and one static random. As indicated in the above table, the public identity address cannot be configured; the static random identity address can be set by calling ble_hs_id_set_rnd() . The address type is selected on a per-GAP-procedure basis. Each time you initiate a GAP procedure, you indicate which address type the device should use for the duration of the procedure. Header #include \"host/ble_hs.h\" Definitions None. Functions Function Description ble_hs_id_copy_addr Retrieves one of the device's identity addresses. ble_hs_id_gen_rnd Generates a new random address. ble_hs_id_set_rnd Sets the device's random address.","title":"toc"},{"location":"network/ble/ble_hs/ble_hs_id/ble_hs_id/#nimble-host-identity-reference","text":"","title":"NimBLE Host Identity Reference"},{"location":"network/ble/ble_hs/ble_hs_id/ble_hs_id/#introduction","text":"The identity API provides facilities for querying and configuring your device's addresses. BLE's addressing scheme is quite involved; the summary that follows is only a brief introduction. BLE defines four address types: Type Description Identity? Configured with Public Address assigned by manufacturer; the three most significant bytes form the manufacturer's OUI. Yes N/A; read from controller at startup. Static random Randomly generated address. Yes ble_hs_id_set_rnd() Resolvable private (RPA) Address randomly generated from an identity address and an identity resolving key (IRK). No N/A; generated by controller periodically. Non-resolvable private (NRPA) Randomly generated address. No ble_hs_id_set_rnd()","title":"Introduction"},{"location":"network/ble/ble_hs/ble_hs_id/ble_hs_id/#identity-addresses","text":"The third column in the above table indicates the identity property of each address type. An identity address never changes, and a device can be identified by one of its unique identity addresses. Non-identity addresses are used by devices supporting BLE privacy. A device using the privacy feature frequently changes its own address to a newly-generated non-identity address. By cycling its address, the device makes it impossible for eavesdroppers to track its location. A device can have up to two identity addresses at once: one public and one static random. As indicated in the above table, the public identity address cannot be configured; the static random identity address can be set by calling ble_hs_id_set_rnd() . The address type is selected on a per-GAP-procedure basis. Each time you initiate a GAP procedure, you indicate which address type the device should use for the duration of the procedure.","title":"Identity Addresses"},{"location":"network/ble/ble_hs/ble_hs_id/ble_hs_id/#header","text":"#include \"host/ble_hs.h\"","title":"Header"},{"location":"network/ble/ble_hs/ble_hs_id/ble_hs_id/#definitions","text":"None.","title":"Definitions"},{"location":"network/ble/ble_hs/ble_hs_id/ble_hs_id/#functions","text":"Function Description ble_hs_id_copy_addr Retrieves one of the device's identity addresses. ble_hs_id_gen_rnd Generates a new random address. ble_hs_id_set_rnd Sets the device's random address.","title":"Functions"},{"location":"network/ble/ble_hs/ble_hs_id/functions/ble_hs_id_copy_addr/","text":"ble_hs_id_copy_addr int ble_hs_id_copy_addr ( uint8_t id_addr_type , uint8_t *out_id_addr , int *out_is_nrpa ) Description Retrieves one of the device's identity addresses. The device can have two identity addresses: one public and one random. The id_addr_type argument specifies which of these two addresses to retrieve. Parameters Parameter Description id_addr_type The type of identity address to retrieve. Valid values are: BLE_ADDR_TYPE_PUBLIC BLE_ADDR_TYPE_RANDOM out_id_addr On success, the requested identity address is copied into this buffer. The buffer must be at least six bytes in size. out_is_nrpa On success, the pointed-to value indicates whether the retrieved address is a non-resolvable private address. Returned values Value Condition 0 Success. BLE_HS_EINVAL An invalid address type was specified. BLE_HS_ENOADDR The device does not have an identity address of the requested type. other Other ble host core code on error.","title":"ble_hs_id_copy_addr"},{"location":"network/ble/ble_hs/ble_hs_id/functions/ble_hs_id_copy_addr/#ble_hs_id_copy_addr","text":"int ble_hs_id_copy_addr ( uint8_t id_addr_type , uint8_t *out_id_addr , int *out_is_nrpa )","title":"ble_hs_id_copy_addr"},{"location":"network/ble/ble_hs/ble_hs_id/functions/ble_hs_id_copy_addr/#description","text":"Retrieves one of the device's identity addresses. The device can have two identity addresses: one public and one random. The id_addr_type argument specifies which of these two addresses to retrieve.","title":"Description"},{"location":"network/ble/ble_hs/ble_hs_id/functions/ble_hs_id_copy_addr/#parameters","text":"Parameter Description id_addr_type The type of identity address to retrieve. Valid values are: BLE_ADDR_TYPE_PUBLIC BLE_ADDR_TYPE_RANDOM out_id_addr On success, the requested identity address is copied into this buffer. The buffer must be at least six bytes in size. out_is_nrpa On success, the pointed-to value indicates whether the retrieved address is a non-resolvable private address.","title":"Parameters"},{"location":"network/ble/ble_hs/ble_hs_id/functions/ble_hs_id_copy_addr/#returned-values","text":"Value Condition 0 Success. BLE_HS_EINVAL An invalid address type was specified. BLE_HS_ENOADDR The device does not have an identity address of the requested type. other Other ble host core code on error.","title":"Returned values"},{"location":"network/ble/ble_hs/ble_hs_id/functions/ble_hs_id_gen_rnd/","text":"ble_hs_id_gen_rnd int ble_hs_id_gen_rnd ( int nrpa , uint8_t *out_addr ) Description Generates a new random address. This function does not configure the device with the new address; the caller can use the address in subsequent operations. Parameters Parameter Description nrpa The type of random address to generate: 0: static 1: non-resolvable private out_addr On success, the generated address gets written here. Returned values Value Condition 0 Success. Core return code Unexpected error.","title":"ble_hs_id_gen_rnd"},{"location":"network/ble/ble_hs/ble_hs_id/functions/ble_hs_id_gen_rnd/#ble_hs_id_gen_rnd","text":"int ble_hs_id_gen_rnd ( int nrpa , uint8_t *out_addr )","title":"ble_hs_id_gen_rnd"},{"location":"network/ble/ble_hs/ble_hs_id/functions/ble_hs_id_gen_rnd/#description","text":"Generates a new random address. This function does not configure the device with the new address; the caller can use the address in subsequent operations.","title":"Description"},{"location":"network/ble/ble_hs/ble_hs_id/functions/ble_hs_id_gen_rnd/#parameters","text":"Parameter Description nrpa The type of random address to generate: 0: static 1: non-resolvable private out_addr On success, the generated address gets written here.","title":"Parameters"},{"location":"network/ble/ble_hs/ble_hs_id/functions/ble_hs_id_gen_rnd/#returned-values","text":"Value Condition 0 Success. Core return code Unexpected error.","title":"Returned values"},{"location":"network/ble/ble_hs/ble_hs_id/functions/ble_hs_id_set_rnd/","text":"ble_hs_id_set_rnd int ble_hs_id_set_rnd ( const uint8_t *rnd_addr ) Description Sets the device's random address. The address type (static vs. non-resolvable private) is inferred from the most-significant byte of the address. The address is specified in host byte order (little-endian!). Parameters Parameter Description rnd_addr The random address to set. Returned values Value Condition 0 Success. Core return code Unexpected error.","title":"ble_hs_id_set_rnd"},{"location":"network/ble/ble_hs/ble_hs_id/functions/ble_hs_id_set_rnd/#ble_hs_id_set_rnd","text":"int ble_hs_id_set_rnd ( const uint8_t *rnd_addr )","title":"ble_hs_id_set_rnd"},{"location":"network/ble/ble_hs/ble_hs_id/functions/ble_hs_id_set_rnd/#description","text":"Sets the device's random address. The address type (static vs. non-resolvable private) is inferred from the most-significant byte of the address. The address is specified in host byte order (little-endian!).","title":"Description"},{"location":"network/ble/ble_hs/ble_hs_id/functions/ble_hs_id_set_rnd/#parameters","text":"Parameter Description rnd_addr The random address to set.","title":"Parameters"},{"location":"network/ble/ble_hs/ble_hs_id/functions/ble_hs_id_set_rnd/#returned-values","text":"Value Condition 0 Success. Core return code Unexpected error.","title":"Returned values"},{"location":"network/ble/ble_hs/init/init/","text":"NimBLE Host Init and Config Reference Introduction This section is a reference on initializing and configuring the NimBLE host. Header #include \"host/ble_hs.h\" Definitions BLE host init and config definitions Functions Function Description ble_hs_init Initializes the NimBLE host. ble_hs_start Synchronizes the host with the controller by sending a sequence of HCI commands. ble_hs_synced Indicates whether the host has synchronized with the controller.","title":"toc"},{"location":"network/ble/ble_hs/init/init/#nimble-host-init-and-config-reference","text":"","title":"NimBLE Host Init and Config Reference"},{"location":"network/ble/ble_hs/init/init/#introduction","text":"This section is a reference on initializing and configuring the NimBLE host.","title":"Introduction"},{"location":"network/ble/ble_hs/init/init/#header","text":"#include \"host/ble_hs.h\"","title":"Header"},{"location":"network/ble/ble_hs/init/init/#definitions","text":"BLE host init and config definitions","title":"Definitions"},{"location":"network/ble/ble_hs/init/init/#functions","text":"Function Description ble_hs_init Initializes the NimBLE host. ble_hs_start Synchronizes the host with the controller by sending a sequence of HCI commands. ble_hs_synced Indicates whether the host has synchronized with the controller.","title":"Functions"},{"location":"network/ble/ble_hs/init/definitions/init_defs/","text":"Other definitions /* Defines the IO capabilities for the local device. */ #define BLE_HS_IO_DISPLAY_ONLY 0x00 #define BLE_HS_IO_DISPLAY_YESNO 0x01 #define BLE_HS_IO_KEYBOARD_ONLY 0x02 #define BLE_HS_IO_NO_INPUT_OUTPUT 0x03 #define BLE_HS_IO_KEYBOARD_DISPLAY 0x04 struct ble_hs_cfg { /*** HCI settings. */ /** * An HCI buffer is a \"flat\" 260-byte buffer. HCI buffers are used by the * controller to send unsolicited events to the host. * * HCI buffers can get tied up when the controller sends lots of * asynchronous / unsolicited events (i.e., non-acks). When the controller * needs to send one of these events, it allocates an HCI buffer, fills it * with the event payload, and puts it on a host queue. If the controller * sends a quick burst of these events, the buffer pool may be exhausted, * preventing the host from sending an HCI command to the controller. * * Every time the controller sends a non-ack HCI event to the host, it also * allocates an OS event (it is unfortunate that these are both called * \"events\"). The OS event is put on the host-parent-task's event queue; * it is what wakes up the host-parent-task and indicates that an HCI event * needs to be processsed. The pool of OS events is allocated with the * same number of elements as the HCI buffer pool. */ uint8_t max_hci_bufs ; /*** Connection settings. */ /** * The maximum number of concurrent connections. This is set * automatically according to the build-time option * NIMBLE_OPT_MAX_CONNECTIONS. */ uint8_t max_connections ; /*** GATT server settings. */ /** * These are acquired at service registration time and never freed. You * need one of these for every service that you register. */ uint16_t max_services ; /** * The total number of in-RAM client characteristic configuration * descriptors (CCCDs). One of these is consumed each time a peer * subscribes to notifications or indications for a characteristic that * your device serves. In addition, at service registration time, the host * uses one of these for each characteristic that supports notifications or * indications. So, the formula which guarantees no resource exhaustion * is: * (num-subscribable-characteristics) * (max-connections + 1) */ uint16_t max_client_configs ; /** * An optional callback that gets executed upon registration of each GATT * resource (service, characteristic, or descriptor). */ ble_gatt_register_fn *gatts_register_cb ; /** * An optional argument that gets passed to the GATT registration * callback. */ void *gatts_register_arg ; /*** GATT client settings. */ /** * The maximum number of concurrent GATT client procedures. When you * initiate a GATT procedure (e.g., read a characteristic, discover * services, etc.), one of these is consumed. The resource is freed when * the procedure completes. */ uint8_t max_gattc_procs ; /*** ATT server settings. */ /** * The total number of local ATT attributes. Attributes are consumed at * service registration time and are never freed. Attributes are used by * GATT server entities: services, characteristics, and descriptors * according to the following formula: * (num-services + (num-characteristics * 2) + num-descriptors) * * Every characteristic that supports indications or notifications * automatically gets a descriptor. All other descriptors are specified by * the application at service registration time. */ uint16_t max_attrs ; /** * A GATT server uses these when a peer performs a \"write long * characteristic values\" or \"write long characteristic descriptors\" * procedure. One of these resources is consumed each time a peer sends a * partial write. These procedures are not used often. */ uint8_t max_prep_entries ; /*** L2CAP settings. */ /** * Each connection requires three L2CAP channels (signal, ATT, and security * manager). In addition, the nimble host may allow channels to be created * \"on the fly\" (connection-oriented channels). This functionality is not * available at the moment, so a safe formula to use is: * (max-connections * 3) */ uint8_t max_l2cap_chans ; /** * The maximum number of concurrent L2CAP signalling procedures. Only one * L2CAP signalling procedure is supported: slave-initiated connection * update. You will never need more of these than the max number of * connections. */ uint8_t max_l2cap_sig_procs ; /** * The maximum number of concurrent security manager procedures. Security * manager procedures include pairing and restoration of a bonded link. */ uint8_t max_l2cap_sm_procs ; /*** Security manager settings. */ uint8_t sm_io_cap ; unsigned sm_oob_data_flag: 1 ; unsigned sm_bonding: 1 ; unsigned sm_mitm: 1 ; unsigned sm_sc: 1 ; unsigned sm_keypress: 1 ; uint8_t sm_our_key_dist ; uint8_t sm_their_key_dist ; /*** Store settings. */ /** * These function callbacks handle persistence of sercurity material * (bonding). */ ble_store_read_fn *store_read_cb ; ble_store_write_fn *store_write_cb ; ble_store_delete_fn *store_delete_cb ; /*** privacy settings */ /** * The frequency at which new resovlable private addresses are generated. * Units are seconds. */ uint16_t rpa_timeout ; }; extern const struct ble_hs_cfg ble_hs_cfg_dflt ;","title":"Init and config definitions"},{"location":"network/ble/ble_hs/init/definitions/init_defs/#other-definitions","text":"/* Defines the IO capabilities for the local device. */ #define BLE_HS_IO_DISPLAY_ONLY 0x00 #define BLE_HS_IO_DISPLAY_YESNO 0x01 #define BLE_HS_IO_KEYBOARD_ONLY 0x02 #define BLE_HS_IO_NO_INPUT_OUTPUT 0x03 #define BLE_HS_IO_KEYBOARD_DISPLAY 0x04 struct ble_hs_cfg { /*** HCI settings. */ /** * An HCI buffer is a \"flat\" 260-byte buffer. HCI buffers are used by the * controller to send unsolicited events to the host. * * HCI buffers can get tied up when the controller sends lots of * asynchronous / unsolicited events (i.e., non-acks). When the controller * needs to send one of these events, it allocates an HCI buffer, fills it * with the event payload, and puts it on a host queue. If the controller * sends a quick burst of these events, the buffer pool may be exhausted, * preventing the host from sending an HCI command to the controller. * * Every time the controller sends a non-ack HCI event to the host, it also * allocates an OS event (it is unfortunate that these are both called * \"events\"). The OS event is put on the host-parent-task's event queue; * it is what wakes up the host-parent-task and indicates that an HCI event * needs to be processsed. The pool of OS events is allocated with the * same number of elements as the HCI buffer pool. */ uint8_t max_hci_bufs ; /*** Connection settings. */ /** * The maximum number of concurrent connections. This is set * automatically according to the build-time option * NIMBLE_OPT_MAX_CONNECTIONS. */ uint8_t max_connections ; /*** GATT server settings. */ /** * These are acquired at service registration time and never freed. You * need one of these for every service that you register. */ uint16_t max_services ; /** * The total number of in-RAM client characteristic configuration * descriptors (CCCDs). One of these is consumed each time a peer * subscribes to notifications or indications for a characteristic that * your device serves. In addition, at service registration time, the host * uses one of these for each characteristic that supports notifications or * indications. So, the formula which guarantees no resource exhaustion * is: * (num-subscribable-characteristics) * (max-connections + 1) */ uint16_t max_client_configs ; /** * An optional callback that gets executed upon registration of each GATT * resource (service, characteristic, or descriptor). */ ble_gatt_register_fn *gatts_register_cb ; /** * An optional argument that gets passed to the GATT registration * callback. */ void *gatts_register_arg ; /*** GATT client settings. */ /** * The maximum number of concurrent GATT client procedures. When you * initiate a GATT procedure (e.g., read a characteristic, discover * services, etc.), one of these is consumed. The resource is freed when * the procedure completes. */ uint8_t max_gattc_procs ; /*** ATT server settings. */ /** * The total number of local ATT attributes. Attributes are consumed at * service registration time and are never freed. Attributes are used by * GATT server entities: services, characteristics, and descriptors * according to the following formula: * (num-services + (num-characteristics * 2) + num-descriptors) * * Every characteristic that supports indications or notifications * automatically gets a descriptor. All other descriptors are specified by * the application at service registration time. */ uint16_t max_attrs ; /** * A GATT server uses these when a peer performs a \"write long * characteristic values\" or \"write long characteristic descriptors\" * procedure. One of these resources is consumed each time a peer sends a * partial write. These procedures are not used often. */ uint8_t max_prep_entries ; /*** L2CAP settings. */ /** * Each connection requires three L2CAP channels (signal, ATT, and security * manager). In addition, the nimble host may allow channels to be created * \"on the fly\" (connection-oriented channels). This functionality is not * available at the moment, so a safe formula to use is: * (max-connections * 3) */ uint8_t max_l2cap_chans ; /** * The maximum number of concurrent L2CAP signalling procedures. Only one * L2CAP signalling procedure is supported: slave-initiated connection * update. You will never need more of these than the max number of * connections. */ uint8_t max_l2cap_sig_procs ; /** * The maximum number of concurrent security manager procedures. Security * manager procedures include pairing and restoration of a bonded link. */ uint8_t max_l2cap_sm_procs ; /*** Security manager settings. */ uint8_t sm_io_cap ; unsigned sm_oob_data_flag: 1 ; unsigned sm_bonding: 1 ; unsigned sm_mitm: 1 ; unsigned sm_sc: 1 ; unsigned sm_keypress: 1 ; uint8_t sm_our_key_dist ; uint8_t sm_their_key_dist ; /*** Store settings. */ /** * These function callbacks handle persistence of sercurity material * (bonding). */ ble_store_read_fn *store_read_cb ; ble_store_write_fn *store_write_cb ; ble_store_delete_fn *store_delete_cb ; /*** privacy settings */ /** * The frequency at which new resovlable private addresses are generated. * Units are seconds. */ uint16_t rpa_timeout ; }; extern const struct ble_hs_cfg ble_hs_cfg_dflt ;","title":"Other definitions"},{"location":"network/ble/ble_hs/init/functions/ble_hs_init/","text":"ble_hs_init int ble_hs_init ( struct os_eventq *app_evq , struct ble_hs_cfg *cfg ) Description Initializes the NimBLE host. This function must be called before the OS is started. The NimBLE stack requires an application task to function. One application task in particular is designated as the \"host parent task\". In addition to application-specific work, the host parent task does work for NimBLE by processing events generated by the host. Parameters Parameter Description app_evq The event queue associated with the host parent task. cfg The set of configuration settings to initialize the host with. Specify null for defaults. Returned values Value Condition 0 Success. Core return code Unexpected error.","title":"ble_hs_init"},{"location":"network/ble/ble_hs/init/functions/ble_hs_init/#ble_hs_init","text":"int ble_hs_init ( struct os_eventq *app_evq , struct ble_hs_cfg *cfg )","title":"ble_hs_init"},{"location":"network/ble/ble_hs/init/functions/ble_hs_init/#description","text":"Initializes the NimBLE host. This function must be called before the OS is started. The NimBLE stack requires an application task to function. One application task in particular is designated as the \"host parent task\". In addition to application-specific work, the host parent task does work for NimBLE by processing events generated by the host.","title":"Description"},{"location":"network/ble/ble_hs/init/functions/ble_hs_init/#parameters","text":"Parameter Description app_evq The event queue associated with the host parent task. cfg The set of configuration settings to initialize the host with. Specify null for defaults.","title":"Parameters"},{"location":"network/ble/ble_hs/init/functions/ble_hs_init/#returned-values","text":"Value Condition 0 Success. Core return code Unexpected error.","title":"Returned values"},{"location":"network/ble/ble_hs/init/functions/ble_hs_start/","text":"ble_hs_start int ble_hs_start ( void ) Description Synchronizes the host with the controller by sending a sequence of HCI commands. This function must be called before any other host functionality is used, but it must be called after both the host and controller are initialized. Typically, the host-parent-task calls this function at the top of its task routine. If the host fails to synchronize with the controller (if the controller is not fully booted, for example), the host will attempt to resynchronize every 100 ms. For this reason, an error return code is not necessarily fatal. Parameters None Returned values Value Condition 0 Success. Core return code Unexpected error.","title":"ble_hs_start"},{"location":"network/ble/ble_hs/init/functions/ble_hs_start/#ble_hs_start","text":"int ble_hs_start ( void )","title":"ble_hs_start"},{"location":"network/ble/ble_hs/init/functions/ble_hs_start/#description","text":"Synchronizes the host with the controller by sending a sequence of HCI commands. This function must be called before any other host functionality is used, but it must be called after both the host and controller are initialized. Typically, the host-parent-task calls this function at the top of its task routine. If the host fails to synchronize with the controller (if the controller is not fully booted, for example), the host will attempt to resynchronize every 100 ms. For this reason, an error return code is not necessarily fatal.","title":"Description"},{"location":"network/ble/ble_hs/init/functions/ble_hs_start/#parameters","text":"None","title":"Parameters"},{"location":"network/ble/ble_hs/init/functions/ble_hs_start/#returned-values","text":"Value Condition 0 Success. Core return code Unexpected error.","title":"Returned values"},{"location":"network/ble/ble_hs/init/functions/ble_hs_synced/","text":"ble_hs_synced int ble_hs_synced ( void ) Description Indicates whether the host has synchronized with the controller. Synchronization must occur before any host procedures can be performed. Parameters None Returned values Value Condition 1 The host and controller are in sync. 0 The host and controller our out of sync.","title":"ble_hs_synced"},{"location":"network/ble/ble_hs/init/functions/ble_hs_synced/#ble_hs_synced","text":"int ble_hs_synced ( void )","title":"ble_hs_synced"},{"location":"network/ble/ble_hs/init/functions/ble_hs_synced/#description","text":"Indicates whether the host has synchronized with the controller. Synchronization must occur before any host procedures can be performed.","title":"Description"},{"location":"network/ble/ble_hs/init/functions/ble_hs_synced/#parameters","text":"None","title":"Parameters"},{"location":"network/ble/ble_hs/init/functions/ble_hs_synced/#returned-values","text":"Value Condition 1 The host and controller are in sync. 0 The host and controller our out of sync.","title":"Returned values"},{"location":"network/ble/ble_hs/other/other/","text":"NimBLE Host Other Reference Introduction This section is a reference on miscellaneous parts of the NimBLE host which don't fit anywhere else! Header #include \"host/ble_hs.h\" Definitions None. Functions Function Description ble_eddystone_set_adv_data_uid Configures the device to advertise eddystone UID beacons. ble_eddystone_set_adv_data_url Configures the device to advertise eddystone URL beacons. ble_hs_mbuf_att_pkt Allocates an mbuf suitable for an ATT command packet. ble_hs_mbuf_from_flat Allocates a an mbuf and fills it with the contents of the specified flat buffer. ble_hs_mbuf_to_flat Copies the contents of an mbuf into the specified flat buffer. ble_ibeacon_set_adv_data Configures the device to advertise iBeacons. ble_uuid_128_to_16 Attempts to convert the supplied 128-bit UUID into its shortened 16-bit form. ble_uuid_16_to_128 Expands a 16-bit UUID into its 128-bit form.","title":"toc"},{"location":"network/ble/ble_hs/other/other/#nimble-host-other-reference","text":"","title":"NimBLE Host Other Reference"},{"location":"network/ble/ble_hs/other/other/#introduction","text":"This section is a reference on miscellaneous parts of the NimBLE host which don't fit anywhere else!","title":"Introduction"},{"location":"network/ble/ble_hs/other/other/#header","text":"#include \"host/ble_hs.h\"","title":"Header"},{"location":"network/ble/ble_hs/other/other/#definitions","text":"None.","title":"Definitions"},{"location":"network/ble/ble_hs/other/other/#functions","text":"Function Description ble_eddystone_set_adv_data_uid Configures the device to advertise eddystone UID beacons. ble_eddystone_set_adv_data_url Configures the device to advertise eddystone URL beacons. ble_hs_mbuf_att_pkt Allocates an mbuf suitable for an ATT command packet. ble_hs_mbuf_from_flat Allocates a an mbuf and fills it with the contents of the specified flat buffer. ble_hs_mbuf_to_flat Copies the contents of an mbuf into the specified flat buffer. ble_ibeacon_set_adv_data Configures the device to advertise iBeacons. ble_uuid_128_to_16 Attempts to convert the supplied 128-bit UUID into its shortened 16-bit form. ble_uuid_16_to_128 Expands a 16-bit UUID into its 128-bit form.","title":"Functions"},{"location":"network/ble/ble_hs/other/functions/ble_eddystone_set_adv_data_uid/","text":"ble_eddystone_set_adv_data_uid int ble_eddystone_set_adv_data_uid ( struct ble_hs_adv_fields *adv_fields , void *uid ) Description Configures the device to advertise eddystone UID beacons. Parameters Parameter Description adv_fields The base advertisement fields to transform into an eddystone beacon. All configured fields are preserved; you probably want to clear this struct before calling this function. uid The 16-byte UID to advertise. Returned values Value Condition 0 Success. BLE_HS_EBUSY Advertising is in progress. BLE_HS_EMSGSIZE The specified data is too large to fit in an advertisement. Core return code Unexpected error.","title":"ble_eddystone_set_adv_data_uid"},{"location":"network/ble/ble_hs/other/functions/ble_eddystone_set_adv_data_uid/#ble_eddystone_set_adv_data_uid","text":"int ble_eddystone_set_adv_data_uid ( struct ble_hs_adv_fields *adv_fields , void *uid )","title":"ble_eddystone_set_adv_data_uid"},{"location":"network/ble/ble_hs/other/functions/ble_eddystone_set_adv_data_uid/#description","text":"Configures the device to advertise eddystone UID beacons.","title":"Description"},{"location":"network/ble/ble_hs/other/functions/ble_eddystone_set_adv_data_uid/#parameters","text":"Parameter Description adv_fields The base advertisement fields to transform into an eddystone beacon. All configured fields are preserved; you probably want to clear this struct before calling this function. uid The 16-byte UID to advertise.","title":"Parameters"},{"location":"network/ble/ble_hs/other/functions/ble_eddystone_set_adv_data_uid/#returned-values","text":"Value Condition 0 Success. BLE_HS_EBUSY Advertising is in progress. BLE_HS_EMSGSIZE The specified data is too large to fit in an advertisement. Core return code Unexpected error.","title":"Returned values"},{"location":"network/ble/ble_hs/other/functions/ble_eddystone_set_adv_data_url/","text":"ble_eddystone_set_adv_data_url int ble_eddystone_set_adv_data_url ( struct ble_hs_adv_fields *adv_fields , uint8_t url_scheme , char *url_body , uint8_t url_body_len , uint8_t url_suffix ) Description Configures the device to advertise eddystone URL beacons. Parameters Parameter Description adv_fields The base advertisement fields to transform into an eddystone beacon. All configured fields are preserved; you probably want to clear this struct before calling this function. url_scheme The prefix of the URL; one of the BLE_EDDYSTONE_URL_SCHEME values. url_body The middle of the URL. Don't include the suffix if there is a suitable suffix code. url_body_len The string length of the url_body argument. url_suffix The suffix of the URL; one of the BLE_EDDYSTONE_URL_SUFFIX values; use BLE_EDDYSTONE_URL_SUFFIX_NONE if the suffix is embedded in the body argument. Returned values Value Condition 0 Success. BLE_HS_EBUSY Advertising is in progress. BLE_HS_EMSGSIZE The specified data is too large to fit in an advertisement. Core return code Unexpected error.","title":"ble_eddystone_set_adv_data_url"},{"location":"network/ble/ble_hs/other/functions/ble_eddystone_set_adv_data_url/#ble_eddystone_set_adv_data_url","text":"int ble_eddystone_set_adv_data_url ( struct ble_hs_adv_fields *adv_fields , uint8_t url_scheme , char *url_body , uint8_t url_body_len , uint8_t url_suffix )","title":"ble_eddystone_set_adv_data_url"},{"location":"network/ble/ble_hs/other/functions/ble_eddystone_set_adv_data_url/#description","text":"Configures the device to advertise eddystone URL beacons.","title":"Description"},{"location":"network/ble/ble_hs/other/functions/ble_eddystone_set_adv_data_url/#parameters","text":"Parameter Description adv_fields The base advertisement fields to transform into an eddystone beacon. All configured fields are preserved; you probably want to clear this struct before calling this function. url_scheme The prefix of the URL; one of the BLE_EDDYSTONE_URL_SCHEME values. url_body The middle of the URL. Don't include the suffix if there is a suitable suffix code. url_body_len The string length of the url_body argument. url_suffix The suffix of the URL; one of the BLE_EDDYSTONE_URL_SUFFIX values; use BLE_EDDYSTONE_URL_SUFFIX_NONE if the suffix is embedded in the body argument.","title":"Parameters"},{"location":"network/ble/ble_hs/other/functions/ble_eddystone_set_adv_data_url/#returned-values","text":"Value Condition 0 Success. BLE_HS_EBUSY Advertising is in progress. BLE_HS_EMSGSIZE The specified data is too large to fit in an advertisement. Core return code Unexpected error.","title":"Returned values"},{"location":"network/ble/ble_hs/other/functions/ble_hs_mbuf_att_pkt/","text":"ble_hs_mbuf_att_pkt struct os_mbuf * ble_hs_mbuf_att_pkt ( void ) Description Allocates an mbuf suitable for an ATT command packet. The resulting packet has sufficient leading space for: o ACM data header o L2CAP B-frame header o Largest ATT command base (prepare write request / response). Parameters None Returned values Value Condition An empty mbuf Success. null Memory exhaustion.","title":"ble_hs_mbuf_att_pkt"},{"location":"network/ble/ble_hs/other/functions/ble_hs_mbuf_att_pkt/#ble_hs_mbuf_att_pkt","text":"struct os_mbuf * ble_hs_mbuf_att_pkt ( void )","title":"ble_hs_mbuf_att_pkt"},{"location":"network/ble/ble_hs/other/functions/ble_hs_mbuf_att_pkt/#description","text":"Allocates an mbuf suitable for an ATT command packet. The resulting packet has sufficient leading space for: o ACM data header o L2CAP B-frame header o Largest ATT command base (prepare write request / response).","title":"Description"},{"location":"network/ble/ble_hs/other/functions/ble_hs_mbuf_att_pkt/#parameters","text":"None","title":"Parameters"},{"location":"network/ble/ble_hs/other/functions/ble_hs_mbuf_att_pkt/#returned-values","text":"Value Condition An empty mbuf Success. null Memory exhaustion.","title":"Returned values"},{"location":"network/ble/ble_hs/other/functions/ble_hs_mbuf_from_flat/","text":"ble_hs_mbuf_from_flat struct os_mbuf * ble_hs_mbuf_from_flat ( const void *buf , uint16_t len ) Description Allocates a an mbuf and fills it with the contents of the specified flat buffer. Parameters Parameter Description buf The flat buffer to copy from. len The length of the flat buffer. Returned values Value Condition A newly-allocated mbuf Success. NULL Memory exhaustion.","title":"ble_hs_mbuf_from_flat"},{"location":"network/ble/ble_hs/other/functions/ble_hs_mbuf_from_flat/#ble_hs_mbuf_from_flat","text":"struct os_mbuf * ble_hs_mbuf_from_flat ( const void *buf , uint16_t len )","title":"ble_hs_mbuf_from_flat"},{"location":"network/ble/ble_hs/other/functions/ble_hs_mbuf_from_flat/#description","text":"Allocates a an mbuf and fills it with the contents of the specified flat buffer.","title":"Description"},{"location":"network/ble/ble_hs/other/functions/ble_hs_mbuf_from_flat/#parameters","text":"Parameter Description buf The flat buffer to copy from. len The length of the flat buffer.","title":"Parameters"},{"location":"network/ble/ble_hs/other/functions/ble_hs_mbuf_from_flat/#returned-values","text":"Value Condition A newly-allocated mbuf Success. NULL Memory exhaustion.","title":"Returned values"},{"location":"network/ble/ble_hs/other/functions/ble_hs_mbuf_to_flat/","text":"ble_hs_mbuf_to_flat int ble_hs_mbuf_to_flat ( const struct os_mbuf *om , void *flat , uint16_t max_len , uint16_t *out_copy_len ) Description Copies the contents of an mbuf into the specified flat buffer. If the flat buffer is too small to contain the mbuf's contents, it is filled to capacity and BLE_HS_EMSGSIZE is returned. Parameters Parameter Description om The mbuf to copy from. flat The destination flat buffer. max_len The size of the flat buffer. out_copy_len The number of bytes actually copied gets written here. Returned values Value Condition 0 Success. BLE_HS_EMSGSIZE The flat buffer is too small to contain the mbuf's contents. Core return code Unexpected error.","title":"ble_hs_mbuf_to_flat"},{"location":"network/ble/ble_hs/other/functions/ble_hs_mbuf_to_flat/#ble_hs_mbuf_to_flat","text":"int ble_hs_mbuf_to_flat ( const struct os_mbuf *om , void *flat , uint16_t max_len , uint16_t *out_copy_len )","title":"ble_hs_mbuf_to_flat"},{"location":"network/ble/ble_hs/other/functions/ble_hs_mbuf_to_flat/#description","text":"Copies the contents of an mbuf into the specified flat buffer. If the flat buffer is too small to contain the mbuf's contents, it is filled to capacity and BLE_HS_EMSGSIZE is returned.","title":"Description"},{"location":"network/ble/ble_hs/other/functions/ble_hs_mbuf_to_flat/#parameters","text":"Parameter Description om The mbuf to copy from. flat The destination flat buffer. max_len The size of the flat buffer. out_copy_len The number of bytes actually copied gets written here.","title":"Parameters"},{"location":"network/ble/ble_hs/other/functions/ble_hs_mbuf_to_flat/#returned-values","text":"Value Condition 0 Success. BLE_HS_EMSGSIZE The flat buffer is too small to contain the mbuf's contents. Core return code Unexpected error.","title":"Returned values"},{"location":"network/ble/ble_hs/other/functions/ble_ibeacon_set_adv_data/","text":"ble_ibeacon_set_adv_data int ble_ibeacon_set_adv_data ( void *uuid128 , uint16_t major , uint16_t minor ) Description Configures the device to advertise iBeacons. Parameters Parameter Description uuid The 128-bit UUID to advertise. major The major version number to include in iBeacons. minor The minor version number to include in iBeacons. Returned values Value Condition 0 Success. BLE_HS_EBUSY Advertising is in progress. Core return code Unexpected error.","title":"ble_ibeacon_set_adv_data"},{"location":"network/ble/ble_hs/other/functions/ble_ibeacon_set_adv_data/#ble_ibeacon_set_adv_data","text":"int ble_ibeacon_set_adv_data ( void *uuid128 , uint16_t major , uint16_t minor )","title":"ble_ibeacon_set_adv_data"},{"location":"network/ble/ble_hs/other/functions/ble_ibeacon_set_adv_data/#description","text":"Configures the device to advertise iBeacons.","title":"Description"},{"location":"network/ble/ble_hs/other/functions/ble_ibeacon_set_adv_data/#parameters","text":"Parameter Description uuid The 128-bit UUID to advertise. major The major version number to include in iBeacons. minor The minor version number to include in iBeacons.","title":"Parameters"},{"location":"network/ble/ble_hs/other/functions/ble_ibeacon_set_adv_data/#returned-values","text":"Value Condition 0 Success. BLE_HS_EBUSY Advertising is in progress. Core return code Unexpected error.","title":"Returned values"},{"location":"network/ble/ble_hs/other/functions/ble_uuid_128_to_16/","text":"ble_uuid_128_to_16 uint16_t ble_uuid_128_to_16 ( const void *uuid128 ) Description Attempts to convert the supplied 128-bit UUID into its shortened 16-bit form. Parameters Parameter Description uuid128 The 128-bit UUID to attempt to convert. This must point to 16 contiguous bytes. Returned values Value Condition A positive 16-bit unsigned integer Success. 0 The uuid cannot be represented in 16 bits.","title":"ble_uuid_128_to_16"},{"location":"network/ble/ble_hs/other/functions/ble_uuid_128_to_16/#ble_uuid_128_to_16","text":"uint16_t ble_uuid_128_to_16 ( const void *uuid128 )","title":"ble_uuid_128_to_16"},{"location":"network/ble/ble_hs/other/functions/ble_uuid_128_to_16/#description","text":"Attempts to convert the supplied 128-bit UUID into its shortened 16-bit form.","title":"Description"},{"location":"network/ble/ble_hs/other/functions/ble_uuid_128_to_16/#parameters","text":"Parameter Description uuid128 The 128-bit UUID to attempt to convert. This must point to 16 contiguous bytes.","title":"Parameters"},{"location":"network/ble/ble_hs/other/functions/ble_uuid_128_to_16/#returned-values","text":"Value Condition A positive 16-bit unsigned integer Success. 0 The uuid cannot be represented in 16 bits.","title":"Returned values"},{"location":"network/ble/ble_hs/other/functions/ble_uuid_16_to_128/","text":"ble_uuid_16_to_128 int ble_uuid_16_to_128 ( uint16_t uuid16 , void *out_uuid128 ) Description Expands a 16-bit UUID into its 128-bit form. Parameters Parameter Description uuid16 The 16-bit UUID to convert. out_uuid128 On success, the resulting 128-bit UUID gets written here. Returned values Value Condition 0 Success. BLE_HS_EINVAL Uuid16 is not a valid 16-bit uuid.","title":"ble_uuid_16_to_128"},{"location":"network/ble/ble_hs/other/functions/ble_uuid_16_to_128/#ble_uuid_16_to_128","text":"int ble_uuid_16_to_128 ( uint16_t uuid16 , void *out_uuid128 )","title":"ble_uuid_16_to_128"},{"location":"network/ble/ble_hs/other/functions/ble_uuid_16_to_128/#description","text":"Expands a 16-bit UUID into its 128-bit form.","title":"Description"},{"location":"network/ble/ble_hs/other/functions/ble_uuid_16_to_128/#parameters","text":"Parameter Description uuid16 The 16-bit UUID to convert. out_uuid128 On success, the resulting 128-bit UUID gets written here.","title":"Parameters"},{"location":"network/ble/ble_hs/other/functions/ble_uuid_16_to_128/#returned-values","text":"Value Condition 0 Success. BLE_HS_EINVAL Uuid16 is not a valid 16-bit uuid.","title":"Returned values"},{"location":"network/ble/bletiny/bletiny_GAP/","text":"GAP API for bletiny Generic Access Profile (GAP) defines the generic procedures related to discovery of Bluetooth devices (idle mode procedures) and link management aspects of connecting to Bluetooth devices (connecting mode procedures). It also defines procedures related to use of different security levels. Several different modes and procedures may be performed simultaneously over an LE physical transport. The following modes and procedures are defined for use over an LE physical transport: Broadcast mode and observation procedure These allow two devices to communicate in a unidirectional connectionless manner using the advertising events. Discovery modes and procedures All devices shall be in either non-discoverable mode or one of the discoverable modes. A device in the discoverable mode shall be in either the general discoverable mode or the limited discoverable mode. A device in non-discoverable mode will not be discovered by any device that is performing either the general discovery procedure or the limited discovery procedure. Connection modes and procedures allow a device to establish a connection to another device. allow updating of parameters of the connection allow termination of the connection Bonding modes and procedures Bonding allows two connected devices to exchange and store security and identity information to create a trusted relationship. Bonding can occur only between two devices in bondable mode. Usage API Item No. Modes and Procedures nimBLE command 1 Broadcast Mode b adv conn=non disc=x Observation Procedure b scan dur=x disc=x type=x filt=x 2 Non-Discoverable mode b adv conn=x disc=non Limited Discoverable mode b adv conn=x disc=ltd General Discoverable mode b adv conn=x disc=gen Limited Discovery procedure b scan dur=x disc=ltd type=active filt=no_wl General Discovery procedure b scan dur=x disc=gen type=active filt=no_wl Name Discovery procedure b scan dur=x b scan cancel b conn peer_addr_type=x peer_addr=x b read uuid=0x2a00 3 Non-connectable mode b adv conn=non disc=x Directed connectable mode b adv conn=dir [own_addr_type=x] [disc=x] [dur=x] Undirected connectable mode b adv conn=und [own_addr_type=x] [disc=x] [dur=x] Auto connection establishment procedure b wl addr_type=x addr=x [addr_type=y addr=y] [...] b conn addr_type=wl General connection establishment procedure b scan dur=x b scan cancel b conn peer_addr_type=x peer_addr=x Selective connection establishment procedure b wl addr_type=x addr=x [addr_type=y addr=y] [...] b scan filt=use_wl dur=x b scan cancel b conn peer_addr_type=x peer_addr=x [own_addr_type=x] Direct connection establishment procedure b conn addr_type=x addr=x [params] Connection parameter update procedure b update conn=x <params> Terminate connection procedure b term conn=x 4 Non-Bondable mode b set sm_data bonding=0 [*] Bondable mode b set sm_data bonding=1 [*] Bonding procedure b sec start conn=x [*] [*] Security is disabled by default in bletiny. To use the bonding modes and procedures, add the -DNIMBLE_OPT_SM=1 cflag to your target. Address Types | bletiny string | Description | Notes | |------------------|---------------| | public | Public address. | | | random | Random static address. | | | rpa_pub | Resolvable private address, public identity. | Not available for all commands. | | rpa_rnd | Resolvable private address, random static identity. | Not available for all commands. | | wl | Use white list; ignore peer_addr parameter. | Only availble for \"conn\" command. | Connection Parameters The Connection parameter definitions can be found in Section 7.8.12 of the BLUETOOTH SPECIFICATION Version 4.2 [Vol 2, Part E]. Name Description bletiny string LE_Scan_Interval Recommendation from the Host on how long the Controller should scan scan_itvl LE_Scan_Window Recommendation from the Host on how frequently the Controller should scan scan_window Peer_Address_Type Whether the peer is using a public or random address (see Address types table). peer_addr_type Peer_Address The 6-byte device address of the peer; ignored if white list is used peer_addr Own_Address_Type The type of address to use when initiating the connection (see Address types table) own_addr_type Conn_Interval_Min Defines minimum allowed connection interval itvl_min Conn_Interval_Max Defines maximum allowed connection interval itvl_max Conn_Latency Defines the maximum allowed connection latency latency Supervision_Timeout Link supervision timeout for the connection. timeout Minimum_CE_Length Informative parameter providing the Controller with the expected minimum length of the connection event min_ce_len Maximum_CE_Length Informative parameter providing the Controller with the expected maximum length of the connection event max_ce_len Duration Number of milliseconds before aborting the connect attempt dur Advertisment Parameters bletiny string Description Notes Default conn Connectable mode See Connectable Modes table. und disc Discoverable mode See Discoverable Modes table. gen own_addr_type The type of address to advertise with See Address Types table. public peer_addr_type The peer's address type Only used for directed advertising; see Address Types table. public peer_addr The peer's address Only used for directed advertising N/A chan_map 0 filt The filter policy See Advertisement Filter Policies table. none itvl_min units=0.625ms non: 100ms; und/dir: 30ms itvl_max units=0.625ms non: 150ms; und/dir: 60ms hd Whether to use high-duty-cycle 0/1 0 dur Milliseconds Forever Advertisement Filter Policies bletiny string Description Notes none No filtering. No whitelist used. Default scan Process all connection requests but only scans from white list. conn Process all scan request but only connection requests from white list. both Ignore all scan and connection requests unless in white list.","title":"GAP in bletiny"},{"location":"network/ble/bletiny/bletiny_GAP/#gap-api-for-bletiny","text":"Generic Access Profile (GAP) defines the generic procedures related to discovery of Bluetooth devices (idle mode procedures) and link management aspects of connecting to Bluetooth devices (connecting mode procedures). It also defines procedures related to use of different security levels. Several different modes and procedures may be performed simultaneously over an LE physical transport. The following modes and procedures are defined for use over an LE physical transport: Broadcast mode and observation procedure These allow two devices to communicate in a unidirectional connectionless manner using the advertising events. Discovery modes and procedures All devices shall be in either non-discoverable mode or one of the discoverable modes. A device in the discoverable mode shall be in either the general discoverable mode or the limited discoverable mode. A device in non-discoverable mode will not be discovered by any device that is performing either the general discovery procedure or the limited discovery procedure. Connection modes and procedures allow a device to establish a connection to another device. allow updating of parameters of the connection allow termination of the connection Bonding modes and procedures Bonding allows two connected devices to exchange and store security and identity information to create a trusted relationship. Bonding can occur only between two devices in bondable mode.","title":"GAP API for bletiny"},{"location":"network/ble/bletiny/bletiny_GAP/#usage-api","text":"Item No. Modes and Procedures nimBLE command 1 Broadcast Mode b adv conn=non disc=x Observation Procedure b scan dur=x disc=x type=x filt=x 2 Non-Discoverable mode b adv conn=x disc=non Limited Discoverable mode b adv conn=x disc=ltd General Discoverable mode b adv conn=x disc=gen Limited Discovery procedure b scan dur=x disc=ltd type=active filt=no_wl General Discovery procedure b scan dur=x disc=gen type=active filt=no_wl Name Discovery procedure b scan dur=x b scan cancel b conn peer_addr_type=x peer_addr=x b read uuid=0x2a00 3 Non-connectable mode b adv conn=non disc=x Directed connectable mode b adv conn=dir [own_addr_type=x] [disc=x] [dur=x] Undirected connectable mode b adv conn=und [own_addr_type=x] [disc=x] [dur=x] Auto connection establishment procedure b wl addr_type=x addr=x [addr_type=y addr=y] [...] b conn addr_type=wl General connection establishment procedure b scan dur=x b scan cancel b conn peer_addr_type=x peer_addr=x Selective connection establishment procedure b wl addr_type=x addr=x [addr_type=y addr=y] [...] b scan filt=use_wl dur=x b scan cancel b conn peer_addr_type=x peer_addr=x [own_addr_type=x] Direct connection establishment procedure b conn addr_type=x addr=x [params] Connection parameter update procedure b update conn=x <params> Terminate connection procedure b term conn=x 4 Non-Bondable mode b set sm_data bonding=0 [*] Bondable mode b set sm_data bonding=1 [*] Bonding procedure b sec start conn=x [*] [*] Security is disabled by default in bletiny. To use the bonding modes and procedures, add the -DNIMBLE_OPT_SM=1 cflag to your target.","title":"Usage API"},{"location":"network/ble/bletiny/bletiny_GAP/#address-types","text":"| bletiny string | Description | Notes | |------------------|---------------| | public | Public address. | | | random | Random static address. | | | rpa_pub | Resolvable private address, public identity. | Not available for all commands. | | rpa_rnd | Resolvable private address, random static identity. | Not available for all commands. | | wl | Use white list; ignore peer_addr parameter. | Only availble for \"conn\" command. |","title":"Address Types"},{"location":"network/ble/bletiny/bletiny_GAP/#connection-parameters","text":"The Connection parameter definitions can be found in Section 7.8.12 of the BLUETOOTH SPECIFICATION Version 4.2 [Vol 2, Part E]. Name Description bletiny string LE_Scan_Interval Recommendation from the Host on how long the Controller should scan scan_itvl LE_Scan_Window Recommendation from the Host on how frequently the Controller should scan scan_window Peer_Address_Type Whether the peer is using a public or random address (see Address types table). peer_addr_type Peer_Address The 6-byte device address of the peer; ignored if white list is used peer_addr Own_Address_Type The type of address to use when initiating the connection (see Address types table) own_addr_type Conn_Interval_Min Defines minimum allowed connection interval itvl_min Conn_Interval_Max Defines maximum allowed connection interval itvl_max Conn_Latency Defines the maximum allowed connection latency latency Supervision_Timeout Link supervision timeout for the connection. timeout Minimum_CE_Length Informative parameter providing the Controller with the expected minimum length of the connection event min_ce_len Maximum_CE_Length Informative parameter providing the Controller with the expected maximum length of the connection event max_ce_len Duration Number of milliseconds before aborting the connect attempt dur","title":"Connection Parameters"},{"location":"network/ble/bletiny/bletiny_GAP/#advertisment-parameters","text":"bletiny string Description Notes Default conn Connectable mode See Connectable Modes table. und disc Discoverable mode See Discoverable Modes table. gen own_addr_type The type of address to advertise with See Address Types table. public peer_addr_type The peer's address type Only used for directed advertising; see Address Types table. public peer_addr The peer's address Only used for directed advertising N/A chan_map 0 filt The filter policy See Advertisement Filter Policies table. none itvl_min units=0.625ms non: 100ms; und/dir: 30ms itvl_max units=0.625ms non: 150ms; und/dir: 60ms hd Whether to use high-duty-cycle 0/1 0 dur Milliseconds Forever","title":"Advertisment Parameters"},{"location":"network/ble/bletiny/bletiny_GAP/#advertisement-filter-policies","text":"bletiny string Description Notes none No filtering. No whitelist used. Default scan Process all connection requests but only scans from white list. conn Process all scan request but only connection requests from white list. both Ignore all scan and connection requests unless in white list.","title":"Advertisement Filter Policies"},{"location":"network/ble/bletiny/bletiny_GATT/","text":"GATT feature API for bletiny GATT(GENERIC ATTRIBUTE PROFILE) describes a service framework using the Attribute Protocol for discovering services, and for reading and writing characteristic values on a peer device. There are 11 features defined in the GATT Profile, and each of the features is mapped to procedures and sub-procedures: Item No. Feature Sub-Procedure nimBLE command 1 Server Configuration Exchange MTU b mtu 2 Primary Service Discovery Discover All Primary Services b disc svc conn=x Discover Primary Services By Service UUID b disc svc conn=x uuid=x 3 Relationship Discovery Find Included Services b find inc_svcs conn=x start=x end=x 4 Characteristic Discovery Discover All Characteristic of a Service b disc chr conn=x start=x end=x Discover Characteristic by UUID b disc chr conn=x start=x end=x uuid=x 5 Characteristic Descriptor Discovery Discover All Characteristic Descriptors b disc dsc conn=x start=x end=x 6 Reading a Characteristic Value Read Characteristic Value b read conn=x attr=x Read Using Characteristic UUID b read conn=x start=x end=x uuid=x Read Long Characteristic Values b read conn=x attr=x long=1 Read Multiple Characteristic Values b read conn=x attr=x attr=y attr=z 7 Writing a Characteristic Value Write Without Response b write conn=x value=0xXX:0xXX no_rsp=1 Signed Write Without Response NOT SUPPORTED Write Characteristic Value b write conn=x attr=x value=0xXX:0xXX Write Long Characteristic Values b write conn=x attr=x value=0xXX:0xXX long=1 Characteristic Value Reliable Writes b write conn=x attr=x value=0xXX:0xXX attr=y value=0xYY:0xYY 8 Notification of a Characteristic Value Notifications Write 0x01:0x00 to CLIENT CONFIGURATION characteristic 9 Indication of a Characteristic Value Indications Write 0x02:0x00 to CLIENT CONFIGURATION characteristic 10 Reading a Characteristic Descriptor Read Characteristic Descriptors b read conn=x attr=x Read Long Characteristic Descriptors b read conn=x attr=x long=1 11 Writing a Characteristic Descriptor Write Characteristic Descriptors b write conn=x value=0xXX:0xXX Write Long Characteristic Descriptors b write conn=x value=0xXX:0xXX long=1 Using NimBLE commands Assuming you have discovered and established a BLE connection with at least one peer device (as explained earlier in API for bletiny app , you can find out what characteristics and services are available over these connections. Here is a recap. To show established connections: b show conn To show discovered services, characteristics, and descriptors: b show chr To show connection RSSI: b show rssi conn=x","title":"GATT in bletiny"},{"location":"network/ble/bletiny/bletiny_GATT/#gatt-feature-api-for-bletiny","text":"GATT(GENERIC ATTRIBUTE PROFILE) describes a service framework using the Attribute Protocol for discovering services, and for reading and writing characteristic values on a peer device. There are 11 features defined in the GATT Profile, and each of the features is mapped to procedures and sub-procedures: Item No. Feature Sub-Procedure nimBLE command 1 Server Configuration Exchange MTU b mtu 2 Primary Service Discovery Discover All Primary Services b disc svc conn=x Discover Primary Services By Service UUID b disc svc conn=x uuid=x 3 Relationship Discovery Find Included Services b find inc_svcs conn=x start=x end=x 4 Characteristic Discovery Discover All Characteristic of a Service b disc chr conn=x start=x end=x Discover Characteristic by UUID b disc chr conn=x start=x end=x uuid=x 5 Characteristic Descriptor Discovery Discover All Characteristic Descriptors b disc dsc conn=x start=x end=x 6 Reading a Characteristic Value Read Characteristic Value b read conn=x attr=x Read Using Characteristic UUID b read conn=x start=x end=x uuid=x Read Long Characteristic Values b read conn=x attr=x long=1 Read Multiple Characteristic Values b read conn=x attr=x attr=y attr=z 7 Writing a Characteristic Value Write Without Response b write conn=x value=0xXX:0xXX no_rsp=1 Signed Write Without Response NOT SUPPORTED Write Characteristic Value b write conn=x attr=x value=0xXX:0xXX Write Long Characteristic Values b write conn=x attr=x value=0xXX:0xXX long=1 Characteristic Value Reliable Writes b write conn=x attr=x value=0xXX:0xXX attr=y value=0xYY:0xYY 8 Notification of a Characteristic Value Notifications Write 0x01:0x00 to CLIENT CONFIGURATION characteristic 9 Indication of a Characteristic Value Indications Write 0x02:0x00 to CLIENT CONFIGURATION characteristic 10 Reading a Characteristic Descriptor Read Characteristic Descriptors b read conn=x attr=x Read Long Characteristic Descriptors b read conn=x attr=x long=1 11 Writing a Characteristic Descriptor Write Characteristic Descriptors b write conn=x value=0xXX:0xXX Write Long Characteristic Descriptors b write conn=x value=0xXX:0xXX long=1","title":"GATT feature API for bletiny"},{"location":"network/ble/bletiny/bletiny_GATT/#using-nimble-commands","text":"Assuming you have discovered and established a BLE connection with at least one peer device (as explained earlier in API for bletiny app , you can find out what characteristics and services are available over these connections. Here is a recap. To show established connections: b show conn To show discovered services, characteristics, and descriptors: b show chr To show connection RSSI: b show rssi conn=x","title":"Using NimBLE commands"},{"location":"network/ble/bletiny/bletiny_advdata/","text":"Advertisement Data Fields This part defines the advertisement data fields used in the bletiny app. For a complete list of all data types and formats used for Extended Inquiry Response (EIR), Advertising Data (AD), and OOB data blocks, refer to the Supplement to the Bluetooth Core Specification, CSSv6, available for download here . Name Definition Details bletiny Notes flags Indicates basic information about the advertiser. Flags used over the LE physical channel are: * Limited Discoverable Mode * General Discoverable Mode * BR/EDR Not Supported * Simultaneous LE and BR/EDR to Same Device Capable (Controller) * Simultaneous LE and BR/EDR to Same Device Capable (Host) NimBLE will auto-calculate if set to 0. uuids16 16-bit Bluetooth Service UUIDs Indicates the Service UUID list is incomplete i.e. more 16-bit Service UUIDs available. 16 bit UUIDs shall only be used if they are assigned by the Bluetooth SIG. Set repeatedly for multiple service UUIDs. uuids16_is_complete 16-bit Bluetooth Service UUIDs Indicates the Service UUID list is complete. 16 bit UUIDs shall only be used if they are assigned by the Bluetooth SIG. uuids32 32-bit Bluetooth Service UUIDs Indicates the Service UUID list is incomplete i.e. more 32-bit Service UUIDs available. 32 bit UUIDs shall only be used if they are assigned by the Bluetooth SIG. Set repeatedly for multiple service UUIDs. uuids32_is_complete 32-bit Bluetooth Service UUIDs Indicates the Service UUID list is complete. 32 bit UUIDs shall only be used if they are assigned by the Bluetooth SIG. uuids128 Global 128-bit Service UUIDs More 128-bit Service UUIDs available. Set repeatedly for multiple service UUIDs. uuids128_is_complete Global 128-bit Service UUIDs Complete list of 128-bit Service UUIDs tx_pwr_lvl TX Power Level Indicates the transmitted power level of the packet containing the data type. The TX Power Level data type may be used to calculate path loss on a received packet using the following equation: pathloss = Tx Power Level \u2013 RSSI where \u201cRSSI\u201d is the received signal strength, in dBm, of the packet received. NimBLE will auto-calculate if set to -128. device_class Class of device Size: 3 octets slave_itvl_range Slave Connection Interval Range Contains the Peripheral\u2019s preferred connection interval range, for all logical connections. Size: 4 Octets . The first 2 octets defines the minimum value for the connection interval in the following manner: connIntervalmin = Conn_Interval_Min * 1.25 ms Conn_Interval_Min range: 0x0006 to 0x0C80 Value of 0xFFFF indicates no specific minimum. The other 2 octets defines the maximum value for the connection interval in the following manner: connIntervalmax = Conn_Interval_Max * 1.25 ms Conn_Interval_Max range: 0x0006 to 0x0C80 Conn_Interval_Max shall be equal to or greater than the Conn_Interval_Min. Value of 0xFFFF indicates no specific maximum. svc_data_uuid16 Service Data - 16 bit UUID Size: 2 or more octets The first 2 octets contain the 16 bit Service UUID followed by additional service data public_tgt_addr Public Target Address Defines the address of one or more intended recipients of an advertisement when one or more devices were bonded using a public address. This data type shall exist only once. It may be sent in either the Advertising or Scan Response data, but not both. appearance Appearance Defines the external appearance of the device. The Appearance data type shall exist only once. It may be sent in either the Advertising or Scan Response data, but not both. adv_itvl Advertising Interval Contains the advInterval value as defined in the Core specification, Volume 6, Part B, Section 4.4.2.2. le_addr LE Bluetooth Device Address Defines the device address of the local device and the address type on the LE transport. le_role LE Role Defines the LE role capabilities of the device. 0x00 Only Peripheral Role supported 0x01 Only Central Role supported 0x02 Peripheral and Central Role supported, Peripheral Role preferred for connection establishment 0x03 Peripheral and Central Role supported, Central Role preferred for connection establishment 0x04 \u2013 0xFF Reserved for future use svc_data_uuid32 Service Data - 32 bit UUID Size: 4 or more octets The first 4 octets contain the 32 bit Service UUID followed by additional service data svc_data_uuid128 Service Data - 128 bit UUID Size: 16 or more octets The first 16 octets contain the 128 bit Service UUID followed by additional service data uri Uniform Resource Identifier (URI) Scheme name string and URI as a UTF-8 string mfg_data Manufacturer Specific data Size: 2 or more octets The first 2 octets contain the Company Identifier Code followed by additional manufacturer specific data eddystone_url","title":"Advertisement Data Fields"},{"location":"network/ble/bletiny/bletiny_advdata/#advertisement-data-fields","text":"This part defines the advertisement data fields used in the bletiny app. For a complete list of all data types and formats used for Extended Inquiry Response (EIR), Advertising Data (AD), and OOB data blocks, refer to the Supplement to the Bluetooth Core Specification, CSSv6, available for download here . Name Definition Details bletiny Notes flags Indicates basic information about the advertiser. Flags used over the LE physical channel are: * Limited Discoverable Mode * General Discoverable Mode * BR/EDR Not Supported * Simultaneous LE and BR/EDR to Same Device Capable (Controller) * Simultaneous LE and BR/EDR to Same Device Capable (Host) NimBLE will auto-calculate if set to 0. uuids16 16-bit Bluetooth Service UUIDs Indicates the Service UUID list is incomplete i.e. more 16-bit Service UUIDs available. 16 bit UUIDs shall only be used if they are assigned by the Bluetooth SIG. Set repeatedly for multiple service UUIDs. uuids16_is_complete 16-bit Bluetooth Service UUIDs Indicates the Service UUID list is complete. 16 bit UUIDs shall only be used if they are assigned by the Bluetooth SIG. uuids32 32-bit Bluetooth Service UUIDs Indicates the Service UUID list is incomplete i.e. more 32-bit Service UUIDs available. 32 bit UUIDs shall only be used if they are assigned by the Bluetooth SIG. Set repeatedly for multiple service UUIDs. uuids32_is_complete 32-bit Bluetooth Service UUIDs Indicates the Service UUID list is complete. 32 bit UUIDs shall only be used if they are assigned by the Bluetooth SIG. uuids128 Global 128-bit Service UUIDs More 128-bit Service UUIDs available. Set repeatedly for multiple service UUIDs. uuids128_is_complete Global 128-bit Service UUIDs Complete list of 128-bit Service UUIDs tx_pwr_lvl TX Power Level Indicates the transmitted power level of the packet containing the data type. The TX Power Level data type may be used to calculate path loss on a received packet using the following equation: pathloss = Tx Power Level \u2013 RSSI where \u201cRSSI\u201d is the received signal strength, in dBm, of the packet received. NimBLE will auto-calculate if set to -128. device_class Class of device Size: 3 octets slave_itvl_range Slave Connection Interval Range Contains the Peripheral\u2019s preferred connection interval range, for all logical connections. Size: 4 Octets . The first 2 octets defines the minimum value for the connection interval in the following manner: connIntervalmin = Conn_Interval_Min * 1.25 ms Conn_Interval_Min range: 0x0006 to 0x0C80 Value of 0xFFFF indicates no specific minimum. The other 2 octets defines the maximum value for the connection interval in the following manner: connIntervalmax = Conn_Interval_Max * 1.25 ms Conn_Interval_Max range: 0x0006 to 0x0C80 Conn_Interval_Max shall be equal to or greater than the Conn_Interval_Min. Value of 0xFFFF indicates no specific maximum. svc_data_uuid16 Service Data - 16 bit UUID Size: 2 or more octets The first 2 octets contain the 16 bit Service UUID followed by additional service data public_tgt_addr Public Target Address Defines the address of one or more intended recipients of an advertisement when one or more devices were bonded using a public address. This data type shall exist only once. It may be sent in either the Advertising or Scan Response data, but not both. appearance Appearance Defines the external appearance of the device. The Appearance data type shall exist only once. It may be sent in either the Advertising or Scan Response data, but not both. adv_itvl Advertising Interval Contains the advInterval value as defined in the Core specification, Volume 6, Part B, Section 4.4.2.2. le_addr LE Bluetooth Device Address Defines the device address of the local device and the address type on the LE transport. le_role LE Role Defines the LE role capabilities of the device. 0x00 Only Peripheral Role supported 0x01 Only Central Role supported 0x02 Peripheral and Central Role supported, Peripheral Role preferred for connection establishment 0x03 Peripheral and Central Role supported, Central Role preferred for connection establishment 0x04 \u2013 0xFF Reserved for future use svc_data_uuid32 Service Data - 32 bit UUID Size: 4 or more octets The first 4 octets contain the 32 bit Service UUID followed by additional service data svc_data_uuid128 Service Data - 128 bit UUID Size: 16 or more octets The first 16 octets contain the 128 bit Service UUID followed by additional service data uri Uniform Resource Identifier (URI) Scheme name string and URI as a UTF-8 string mfg_data Manufacturer Specific data Size: 2 or more octets The first 2 octets contain the Company Identifier Code followed by additional manufacturer specific data eddystone_url","title":"Advertisement Data Fields"},{"location":"network/ble/bletiny/bletiny_api/","text":"API for bletiny app \"bletiny\" is one of the sample applications that come with Mynewt. It is a simple shell application which provides a basic interface to the host-side of the BLE stack. \"bletiny\" includes all the possible roles (Central/Peripheral) and they may be run simultaneously. You can run bletiny on a board and issue commands that make it behave as a central or a peripheral with different peers. Highlighted below are some of the ways you can use the API to establish connections and discover services and characteristics from peer devices. For descriptions of the full API, go to the next sections on GAP in bletiny and GATT in bletiny . All bletiny commands are prefixed with b . This prefix distinguished bletiny commands from other shell commands that are implemented by other Mynewt packages. Set device address. On startup, bletiny has the following identity address configuration: Public address: 0a:0b:0c:0d:0e:0f Random address: None The below set commands can be used to change the address configuration: b set addr_type=public addr=<device-address> b set addr_type=random addr=<device-address> For example: b set addr_type=public addr=01:02:03:04:05:06 b set addr_type=random addr=c1:aa:bb:cc:dd:ee The address configuration can be viewed with the b show addr command, as follows: b show addr public_id_addr=01:02:03:04:05:06 random_id_addr=c1:aa:bb:cc:dd:ee Initiate a direct connection to a device In this case, your board is acting as a central and initiating a connection with another BLE device. The example assumes you know the address of the peer, either by scanning for available peers or because you have set up the peer yourself. b conn own_addr_type=public peer_addr_type=public peer_addr=d4:f5:13:53:d2:43 connection established; handle=1 our_ota_addr_type=0 our_ota_addr=0a:0b:0c:0d:0e:0f out_id_addr_type=0 our_id_addr=0a:0b:0c:0d:0e:0f peer_addr_type=0 peer_addr=43:d2:53:13:f5:d4 conn_itvl=40 conn_latency=0 supervision_timeout=256 encrypted=0 authenticated=0 bonded=0 The handle=1 in the output indicates that it is connection-1. Configure advertisements to include device name In this case, your board is acting as a peripheral. b set adv_data name=<your-device-name> Begin sending undirected general advertisements In this case, your board is acting as a peripheral. b adv conn=und disc=gen Show established connections. b show conn Discover and display peer's services, characteristics, and descriptors. This is how you discover and then display the services of the peer you established earlier across connection-1. b disc full conn=1 b show chr [ts=132425ssb, mod=64 level=2] CONNECTION: handle=1 addr=d4:f5:13:53:d2:43 [ts=132428ssb, mod=64 level=2] start=1 end=5 uuid=0x1800 [ts=132433ssb, mod=64 level=2] start=6 end=16 uuid=0x1808 [ts=132437ssb, mod=64 level=2] start=17 end=31 uuid=0x180a [ts=132441ssb, mod=64 level=2] start=32 end=65535 uuid=00000000-0000-1000-1000000000000000 Read an attribute belonging to the peer b read conn=1 attr=21 Write to an attribute belonging to the peer b write conn=1 attr=3 value=0x01:0x02:0x03 Perform a passive scan This is how you tell your board to listen to all advertisements around it. The duration is specified in ms. b scan dur=1000 type=passive filt=no_wl","title":"toc"},{"location":"network/ble/bletiny/bletiny_api/#api-for-bletiny-app","text":"\"bletiny\" is one of the sample applications that come with Mynewt. It is a simple shell application which provides a basic interface to the host-side of the BLE stack. \"bletiny\" includes all the possible roles (Central/Peripheral) and they may be run simultaneously. You can run bletiny on a board and issue commands that make it behave as a central or a peripheral with different peers. Highlighted below are some of the ways you can use the API to establish connections and discover services and characteristics from peer devices. For descriptions of the full API, go to the next sections on GAP in bletiny and GATT in bletiny . All bletiny commands are prefixed with b . This prefix distinguished bletiny commands from other shell commands that are implemented by other Mynewt packages.","title":"API for bletiny app"},{"location":"network/ble/bletiny/bletiny_api/#set-device-address","text":"On startup, bletiny has the following identity address configuration: Public address: 0a:0b:0c:0d:0e:0f Random address: None The below set commands can be used to change the address configuration: b set addr_type=public addr=<device-address> b set addr_type=random addr=<device-address> For example: b set addr_type=public addr=01:02:03:04:05:06 b set addr_type=random addr=c1:aa:bb:cc:dd:ee The address configuration can be viewed with the b show addr command, as follows: b show addr public_id_addr=01:02:03:04:05:06 random_id_addr=c1:aa:bb:cc:dd:ee","title":"Set device address."},{"location":"network/ble/bletiny/bletiny_api/#initiate-a-direct-connection-to-a-device","text":"In this case, your board is acting as a central and initiating a connection with another BLE device. The example assumes you know the address of the peer, either by scanning for available peers or because you have set up the peer yourself. b conn own_addr_type=public peer_addr_type=public peer_addr=d4:f5:13:53:d2:43 connection established; handle=1 our_ota_addr_type=0 our_ota_addr=0a:0b:0c:0d:0e:0f out_id_addr_type=0 our_id_addr=0a:0b:0c:0d:0e:0f peer_addr_type=0 peer_addr=43:d2:53:13:f5:d4 conn_itvl=40 conn_latency=0 supervision_timeout=256 encrypted=0 authenticated=0 bonded=0 The handle=1 in the output indicates that it is connection-1.","title":"Initiate a direct connection to a device"},{"location":"network/ble/bletiny/bletiny_api/#configure-advertisements-to-include-device-name","text":"In this case, your board is acting as a peripheral. b set adv_data name=<your-device-name>","title":"Configure advertisements to include device name"},{"location":"network/ble/bletiny/bletiny_api/#begin-sending-undirected-general-advertisements","text":"In this case, your board is acting as a peripheral. b adv conn=und disc=gen","title":"Begin sending undirected general advertisements"},{"location":"network/ble/bletiny/bletiny_api/#show-established-connections","text":"b show conn","title":"Show established connections."},{"location":"network/ble/bletiny/bletiny_api/#discover-and-display-peers-services-characteristics-and-descriptors","text":"This is how you discover and then display the services of the peer you established earlier across connection-1. b disc full conn=1 b show chr [ts=132425ssb, mod=64 level=2] CONNECTION: handle=1 addr=d4:f5:13:53:d2:43 [ts=132428ssb, mod=64 level=2] start=1 end=5 uuid=0x1800 [ts=132433ssb, mod=64 level=2] start=6 end=16 uuid=0x1808 [ts=132437ssb, mod=64 level=2] start=17 end=31 uuid=0x180a [ts=132441ssb, mod=64 level=2] start=32 end=65535 uuid=00000000-0000-1000-1000000000000000","title":"Discover and display peer's services, characteristics, and descriptors."},{"location":"network/ble/bletiny/bletiny_api/#read-an-attribute-belonging-to-the-peer","text":"b read conn=1 attr=21","title":"Read an attribute belonging to the peer"},{"location":"network/ble/bletiny/bletiny_api/#write-to-an-attribute-belonging-to-the-peer","text":"b write conn=1 attr=3 value=0x01:0x02:0x03","title":"Write to an attribute belonging to the peer"},{"location":"network/ble/bletiny/bletiny_api/#perform-a-passive-scan","text":"This is how you tell your board to listen to all advertisements around it. The duration is specified in ms. b scan dur=1000 type=passive filt=no_wl","title":"Perform a passive scan"},{"location":"network/ble/ini_stack/ble_add_cpu/","text":"Add cputime The NimBLE stack requires \"cputime\". This is provided by the Mynewt HAL of the same name. The cputime HAL provides a high resolution timer that is used by the nimble stack (as the BLE specification requires a fairly high resolution timer and has fairly tight timing requirements). The cputime HAL allows the user to specify the timer resolution as different applications may require a different resolution. While the Nimble stack does not require a specific timer resolution per se, a resolution that is too large may affect performance and power efficiency. A suggested clock rate for HAL cputime for the nimble stack is 1 MHz, or 1 microsecond per cputime tick. This provides enough resolution for most needs while providing the Nimble stack enough resolution to implement the BLE specification. Add the initialization of cputime to your application: #include \"hal/hal_cputime.h\" int main ( void ) { int rc ; /* Initialize OS */ os_init (); /* Set cputime to count at 1 usec increments */ rc = cputime_init ( 1000000 ); assert ( rc == 0 ); /* Start the OS */ os_start (); /* os start should never return. If it does, this should be an error */ assert ( 0 ); }","title":"Add cputime"},{"location":"network/ble/ini_stack/ble_add_cpu/#add-cputime","text":"The NimBLE stack requires \"cputime\". This is provided by the Mynewt HAL of the same name. The cputime HAL provides a high resolution timer that is used by the nimble stack (as the BLE specification requires a fairly high resolution timer and has fairly tight timing requirements). The cputime HAL allows the user to specify the timer resolution as different applications may require a different resolution. While the Nimble stack does not require a specific timer resolution per se, a resolution that is too large may affect performance and power efficiency. A suggested clock rate for HAL cputime for the nimble stack is 1 MHz, or 1 microsecond per cputime tick. This provides enough resolution for most needs while providing the Nimble stack enough resolution to implement the BLE specification. Add the initialization of cputime to your application: #include \"hal/hal_cputime.h\" int main ( void ) { int rc ; /* Initialize OS */ os_init (); /* Set cputime to count at 1 usec increments */ rc = cputime_init ( 1000000 ); assert ( rc == 0 ); /* Start the OS */ os_start (); /* os start should never return. If it does, this should be an error */ assert ( 0 ); }","title":"Add cputime"},{"location":"network/ble/ini_stack/ble_consolepkg/","text":"Initializing the console package The console is also required by the Nimble stack. The console is currently used for log output so it needs to be initialized. For this example, we are not going to use a console receive callback. All this means is that input from the console will not be accepted by default; the developer will have to install their own handler or use one provided by another package (the shell, for example). Just like statistics, the console is initialized by calling the console initialization function console_init() . #include \"console/console.h\" int main ( void ) { int rc ; /* Initialize OS */ os_init (); /* Set cputime to count at 1 usec increments */ rc = cputime_init ( 1000000 ); assert ( rc == 0 ); /* Create memory pool for Nimble packets and register with Msys */ rc = os_mempool_init ( &g_mbuf_mempool , MBUF_NUM_MBUFS , MBUF_MEMBLOCK_SIZE , &g_mbuf_buffer [ 0 ], \"mbuf_pool\" ); assert ( rc == 0 ); rc = os_mbuf_pool_init ( &g_mbuf_pool , &g_mbuf_mempool , MBUF_MEMBLOCK_SIZE , MBUF_NUM_MBUFS ); assert ( rc == 0 ); rc = os_msys_register ( &g_mbuf_pool ); assert ( rc == 0 ); /* Initialize our device address */ g_dev_addr [ 0 ] = 0x33 ; g_dev_addr [ 1 ] = 0x22 ; g_dev_addr [ 2 ] = 0x11 ; g_dev_addr [ 3 ] = 0xcc ; g_dev_addr [ 4 ] = 0xbb ; g_dev_addr [ 5 ] = 0x0a ; /* Initialize the statistics package */ rc = stats_module_init (); assert ( rc == 0 ); /* Init the console */ rc = console_init ( NULL ); assert ( rc == 0 ); /* Start the OS */ os_start (); /* os start should never return. If it does, this should be an error */ assert ( 0 ); }","title":"Initialize console pkg"},{"location":"network/ble/ini_stack/ble_consolepkg/#initializing-the-console-package","text":"The console is also required by the Nimble stack. The console is currently used for log output so it needs to be initialized. For this example, we are not going to use a console receive callback. All this means is that input from the console will not be accepted by default; the developer will have to install their own handler or use one provided by another package (the shell, for example). Just like statistics, the console is initialized by calling the console initialization function console_init() . #include \"console/console.h\" int main ( void ) { int rc ; /* Initialize OS */ os_init (); /* Set cputime to count at 1 usec increments */ rc = cputime_init ( 1000000 ); assert ( rc == 0 ); /* Create memory pool for Nimble packets and register with Msys */ rc = os_mempool_init ( &g_mbuf_mempool , MBUF_NUM_MBUFS , MBUF_MEMBLOCK_SIZE , &g_mbuf_buffer [ 0 ], \"mbuf_pool\" ); assert ( rc == 0 ); rc = os_mbuf_pool_init ( &g_mbuf_pool , &g_mbuf_mempool , MBUF_MEMBLOCK_SIZE , MBUF_NUM_MBUFS ); assert ( rc == 0 ); rc = os_msys_register ( &g_mbuf_pool ); assert ( rc == 0 ); /* Initialize our device address */ g_dev_addr [ 0 ] = 0x33 ; g_dev_addr [ 1 ] = 0x22 ; g_dev_addr [ 2 ] = 0x11 ; g_dev_addr [ 3 ] = 0xcc ; g_dev_addr [ 4 ] = 0xbb ; g_dev_addr [ 5 ] = 0x0a ; /* Initialize the statistics package */ rc = stats_module_init (); assert ( rc == 0 ); /* Init the console */ rc = console_init ( NULL ); assert ( rc == 0 ); /* Start the OS */ os_start (); /* os start should never return. If it does, this should be an error */ assert ( 0 ); }","title":"Initializing the console package"},{"location":"network/ble/ini_stack/ble_controller_ini/","text":"Initialize the NimBLE controller The NimBLE controller is initialized via a call to ble_ll_init() . This function is declared as follows: int ble_ll_init ( uint8_t ll_task_prio , uint8_t num_acl_pkts , uint16_t acl_pkt_size ) This function's parameters are documented below. Parameter Description prio The priority of the NimBLE controller task. A lower number corresponds to higher priority. num_acl_pkts The maximum number of outstanding data packets that the controller will accept from the host. acl_pkt_size The maximum data packet size that the controller will accept from the host. prio : If you are not familiar with multitasking, preemptive operating systems we highly encourage you to read the Core OS section of Mynewt OS manual. It is up to the application developer to decide the priority of tasks in the system. Note that the lower the priority number the higher the priority in the OS. For example, if a task is running at priority 5 and a task at priority 3 wants to run, the task at priority 5 gets preempted as the other task is a higher proiority. In the example shown below, the LL task is configured to have the highest priority (priority 0). We recommend making the BLE LL task the highest priority task in your application as it has fairly rigorous timing requirements and allowing other tasks to preempt the LL task could cause undesirable behavior. Note that we do not force this to be the case as an application may require a task to be even higher priority than the LL task. Just be warned: a task higher in priority than the LL task should not perform actions that take too long; even a few milliseconds could cause undesirable behavior. num_acl_pkts and acl_pkt_size : These two parameters are used to limit the amount of data the host tries to send through the controller. NimBLE uses the msys facility for allocating data packets, so the product of these arguments must not be larger than the total amount of memory allocated for msys. The below example uses some values that are reasonable for most uses. #include \"controller/ble_ll.h\" int main ( void ) { int rc ; struct ble_hs_cfg cfg ; /* Initialize OS */ os_init (); /* Set cputime to count at 1 usec increments */ rc = cputime_init ( 1000000 ); assert ( rc == 0 ); /* Create memory pool for NimBLE packets and register with Msys */ rc = os_mempool_init ( &g_mbuf_mempool , MBUF_NUM_MBUFS , MBUF_MEMBLOCK_SIZE , &g_mbuf_buffer [ 0 ], \"mbuf_pool\" ); assert ( rc == 0 ); rc = os_mbuf_pool_init ( &g_mbuf_pool , &g_mbuf_mempool , MBUF_MEMBLOCK_SIZE , MBUF_NUM_MBUFS ); assert ( rc == 0 ); rc = os_msys_register ( &g_mbuf_pool ); assert ( rc == 0 ); /* Initialize our device address */ g_dev_addr [ 0 ] = 0x33 ; g_dev_addr [ 1 ] = 0x22 ; g_dev_addr [ 2 ] = 0x11 ; g_dev_addr [ 3 ] = 0xcc ; g_dev_addr [ 4 ] = 0xbb ; g_dev_addr [ 5 ] = 0x0a ; /* Initialize the statistics package */ rc = stats_module_init (); assert ( rc == 0 ); /* Initialize the BLE LL */ rc = ble_ll_init ( 0 , 7 , 260 ); assert ( rc == 0 ); /* Start the OS */ os_start (); /* os start should never return. If it does, this should be an error */ assert ( 0 ); }","title":"Initialize controller"},{"location":"network/ble/ini_stack/ble_controller_ini/#initialize-the-nimble-controller","text":"The NimBLE controller is initialized via a call to ble_ll_init() . This function is declared as follows: int ble_ll_init ( uint8_t ll_task_prio , uint8_t num_acl_pkts , uint16_t acl_pkt_size ) This function's parameters are documented below. Parameter Description prio The priority of the NimBLE controller task. A lower number corresponds to higher priority. num_acl_pkts The maximum number of outstanding data packets that the controller will accept from the host. acl_pkt_size The maximum data packet size that the controller will accept from the host. prio : If you are not familiar with multitasking, preemptive operating systems we highly encourage you to read the Core OS section of Mynewt OS manual. It is up to the application developer to decide the priority of tasks in the system. Note that the lower the priority number the higher the priority in the OS. For example, if a task is running at priority 5 and a task at priority 3 wants to run, the task at priority 5 gets preempted as the other task is a higher proiority. In the example shown below, the LL task is configured to have the highest priority (priority 0). We recommend making the BLE LL task the highest priority task in your application as it has fairly rigorous timing requirements and allowing other tasks to preempt the LL task could cause undesirable behavior. Note that we do not force this to be the case as an application may require a task to be even higher priority than the LL task. Just be warned: a task higher in priority than the LL task should not perform actions that take too long; even a few milliseconds could cause undesirable behavior. num_acl_pkts and acl_pkt_size : These two parameters are used to limit the amount of data the host tries to send through the controller. NimBLE uses the msys facility for allocating data packets, so the product of these arguments must not be larger than the total amount of memory allocated for msys. The below example uses some values that are reasonable for most uses. #include \"controller/ble_ll.h\" int main ( void ) { int rc ; struct ble_hs_cfg cfg ; /* Initialize OS */ os_init (); /* Set cputime to count at 1 usec increments */ rc = cputime_init ( 1000000 ); assert ( rc == 0 ); /* Create memory pool for NimBLE packets and register with Msys */ rc = os_mempool_init ( &g_mbuf_mempool , MBUF_NUM_MBUFS , MBUF_MEMBLOCK_SIZE , &g_mbuf_buffer [ 0 ], \"mbuf_pool\" ); assert ( rc == 0 ); rc = os_mbuf_pool_init ( &g_mbuf_pool , &g_mbuf_mempool , MBUF_MEMBLOCK_SIZE , MBUF_NUM_MBUFS ); assert ( rc == 0 ); rc = os_msys_register ( &g_mbuf_pool ); assert ( rc == 0 ); /* Initialize our device address */ g_dev_addr [ 0 ] = 0x33 ; g_dev_addr [ 1 ] = 0x22 ; g_dev_addr [ 2 ] = 0x11 ; g_dev_addr [ 3 ] = 0xcc ; g_dev_addr [ 4 ] = 0xbb ; g_dev_addr [ 5 ] = 0x0a ; /* Initialize the statistics package */ rc = stats_module_init (); assert ( rc == 0 ); /* Initialize the BLE LL */ rc = ble_ll_init ( 0 , 7 , 260 ); assert ( rc == 0 ); /* Start the OS */ os_start (); /* os start should never return. If it does, this should be an error */ assert ( 0 ); }","title":"Initialize the NimBLE controller"},{"location":"network/ble/ini_stack/ble_devadd/","text":"Initialize the Device Address The BLE specification requires that devices have an address (called a device address). This address can be either a public device address or a random device address. The current Nimble stack implementation requires that these addresses be defined somewhere in the application; they are not defined within the Nimble stack itself. This was done so that the entire application could have access to these addresses. We expect that we will move these addresses into the Nimble stack in a future release. The two variables that must be defined are named g_dev_addr (public device address) and g_random_addr (static random address). The device address must be initialized prior to initializing the Nimble stack. The random address does not have to be initialized ahead of time as it is possible to set the random address in the Nimble controller when it is running. In this example, we only initialize the device address. The company OUI in this example is 0a:bb:cc; the unique portion is 11:22:33 for a device address equal to 0a:bb:cc:11:22:33. Note that we store the address in little endian order as BLE expects the OUI to be in the most significant bytes. /* Our global device address (public) */ uint8_t g_dev_addr [ BLE_DEV_ADDR_LEN ]; /* Our random address (static) */ uint8_t g_random_addr [ BLE_DEV_ADDR_LEN ]; int main ( void ) { int rc ; /* Initialize OS */ os_init (); /* Set cputime to count at 1 usec increments */ rc = cputime_init ( 1000000 ); assert ( rc == 0 ); /* Create memory pool for Nimble packets and register with Msys */ rc = os_mempool_init ( &g_mbuf_mempool , MBUF_NUM_MBUFS , MBUF_MEMBLOCK_SIZE , &g_mbuf_buffer [ 0 ], \"mbuf_pool\" ); assert ( rc == 0 ); rc = os_mbuf_pool_init ( &g_mbuf_pool , &g_mbuf_mempool , MBUF_MEMBLOCK_SIZE , MBUF_NUM_MBUFS ); assert ( rc == 0 ); rc = os_msys_register ( &g_mbuf_pool ); assert ( rc == 0 ); /* Initialize our device address */ g_dev_addr [ 0 ] = 0x33 ; g_dev_addr [ 1 ] = 0x22 ; g_dev_addr [ 2 ] = 0x11 ; g_dev_addr [ 3 ] = 0xcc ; g_dev_addr [ 4 ] = 0xbb ; g_dev_addr [ 5 ] = 0x0a ; /* Start the OS */ os_start (); /* os start should never return. If it does, this should be an error */ assert ( 0 ); }","title":"Initialize device addr"},{"location":"network/ble/ini_stack/ble_devadd/#initialize-the-device-address","text":"The BLE specification requires that devices have an address (called a device address). This address can be either a public device address or a random device address. The current Nimble stack implementation requires that these addresses be defined somewhere in the application; they are not defined within the Nimble stack itself. This was done so that the entire application could have access to these addresses. We expect that we will move these addresses into the Nimble stack in a future release. The two variables that must be defined are named g_dev_addr (public device address) and g_random_addr (static random address). The device address must be initialized prior to initializing the Nimble stack. The random address does not have to be initialized ahead of time as it is possible to set the random address in the Nimble controller when it is running. In this example, we only initialize the device address. The company OUI in this example is 0a:bb:cc; the unique portion is 11:22:33 for a device address equal to 0a:bb:cc:11:22:33. Note that we store the address in little endian order as BLE expects the OUI to be in the most significant bytes. /* Our global device address (public) */ uint8_t g_dev_addr [ BLE_DEV_ADDR_LEN ]; /* Our random address (static) */ uint8_t g_random_addr [ BLE_DEV_ADDR_LEN ]; int main ( void ) { int rc ; /* Initialize OS */ os_init (); /* Set cputime to count at 1 usec increments */ rc = cputime_init ( 1000000 ); assert ( rc == 0 ); /* Create memory pool for Nimble packets and register with Msys */ rc = os_mempool_init ( &g_mbuf_mempool , MBUF_NUM_MBUFS , MBUF_MEMBLOCK_SIZE , &g_mbuf_buffer [ 0 ], \"mbuf_pool\" ); assert ( rc == 0 ); rc = os_mbuf_pool_init ( &g_mbuf_pool , &g_mbuf_mempool , MBUF_MEMBLOCK_SIZE , MBUF_NUM_MBUFS ); assert ( rc == 0 ); rc = os_msys_register ( &g_mbuf_pool ); assert ( rc == 0 ); /* Initialize our device address */ g_dev_addr [ 0 ] = 0x33 ; g_dev_addr [ 1 ] = 0x22 ; g_dev_addr [ 2 ] = 0x11 ; g_dev_addr [ 3 ] = 0xcc ; g_dev_addr [ 4 ] = 0xbb ; g_dev_addr [ 5 ] = 0x0a ; /* Start the OS */ os_start (); /* os start should never return. If it does, this should be an error */ assert ( 0 ); }","title":"Initialize the Device Address"},{"location":"network/ble/ini_stack/ble_host_ini/","text":"Initialize the NimBLE host The Nimble host is initialized via a call to ble_hs_init() . This function is declared as follows: int ble_hs_init ( struct os_eventq *parent_evq , struct ble_hs_cfg *cfg ) The parameters are documented below. Parameter Description parent_evq The OS event queue that the host should use to schedule host-related operations. cfg A pointer to the desired host configuration, or NULL if you want to use the default settings. parent_evq : This is the event queue associated with the host parent task . cfg : As mentioned above, passing a cfg value of NULL will initialize the Nimble host with the default configuration. This is convenient while familiarizing yourself with the Nimble stack, but ultimately you will probably want to use a custom configuration. For more information on configuring the host, see the Nimble Configuration Guide (TBD). Continuing with our running example, we now add Nimble host initialization to the main() function. This application uses the default host configuration, so it specifies NULL as the second argument to ble_hs_init() . #include \"host/ble_hs.h\" int main ( void ) { int rc ; /* Initialize OS */ os_init (); /* Set cputime to count at 1 usec increments */ rc = cputime_init ( 1000000 ); assert ( rc == 0 ); /* Create memory pool for Nimble packets and register with Msys */ rc = os_mempool_init ( &g_mbuf_mempool , MBUF_NUM_MBUFS , MBUF_MEMBLOCK_SIZE , &g_mbuf_buffer [ 0 ], \"mbuf_pool\" ); assert ( rc == 0 ); rc = os_mbuf_pool_init ( &g_mbuf_pool , &g_mbuf_mempool , MBUF_MEMBLOCK_SIZE , MBUF_NUM_MBUFS ); assert ( rc == 0 ); rc = os_msys_register ( &g_mbuf_pool ); assert ( rc == 0 ); /* Initialize our device address */ g_dev_addr [ 0 ] = 0x33 ; g_dev_addr [ 1 ] = 0x22 ; g_dev_addr [ 2 ] = 0x11 ; g_dev_addr [ 3 ] = 0xcc ; g_dev_addr [ 4 ] = 0xbb ; g_dev_addr [ 5 ] = 0x0a ; /* Initialize the statistics package */ rc = stats_module_init (); assert ( rc == 0 ); /* Initialize the BLE LL */ rc = ble_ll_init ( 0 , 7 , 260 ); assert ( rc == 0 ); /* Initialize the application task. */ os_eventq_init ( &app_evq ); os_task_init ( &app_task , \"app\" , app_task_handler , NULL , 1 , OS_WAIT_FOREVER , app_stack , APP_STACK_SIZE ); /* Initialize the BLE host. */ rc = ble_hs_init ( &app_evq , NULL ); assert ( rc == 0 ); /* Start the OS */ os_start (); /* os start should never return. If it does, this should be an error */ assert ( 0 ); }","title":"Initialize host"},{"location":"network/ble/ini_stack/ble_host_ini/#initialize-the-nimble-host","text":"The Nimble host is initialized via a call to ble_hs_init() . This function is declared as follows: int ble_hs_init ( struct os_eventq *parent_evq , struct ble_hs_cfg *cfg ) The parameters are documented below. Parameter Description parent_evq The OS event queue that the host should use to schedule host-related operations. cfg A pointer to the desired host configuration, or NULL if you want to use the default settings. parent_evq : This is the event queue associated with the host parent task . cfg : As mentioned above, passing a cfg value of NULL will initialize the Nimble host with the default configuration. This is convenient while familiarizing yourself with the Nimble stack, but ultimately you will probably want to use a custom configuration. For more information on configuring the host, see the Nimble Configuration Guide (TBD). Continuing with our running example, we now add Nimble host initialization to the main() function. This application uses the default host configuration, so it specifies NULL as the second argument to ble_hs_init() . #include \"host/ble_hs.h\" int main ( void ) { int rc ; /* Initialize OS */ os_init (); /* Set cputime to count at 1 usec increments */ rc = cputime_init ( 1000000 ); assert ( rc == 0 ); /* Create memory pool for Nimble packets and register with Msys */ rc = os_mempool_init ( &g_mbuf_mempool , MBUF_NUM_MBUFS , MBUF_MEMBLOCK_SIZE , &g_mbuf_buffer [ 0 ], \"mbuf_pool\" ); assert ( rc == 0 ); rc = os_mbuf_pool_init ( &g_mbuf_pool , &g_mbuf_mempool , MBUF_MEMBLOCK_SIZE , MBUF_NUM_MBUFS ); assert ( rc == 0 ); rc = os_msys_register ( &g_mbuf_pool ); assert ( rc == 0 ); /* Initialize our device address */ g_dev_addr [ 0 ] = 0x33 ; g_dev_addr [ 1 ] = 0x22 ; g_dev_addr [ 2 ] = 0x11 ; g_dev_addr [ 3 ] = 0xcc ; g_dev_addr [ 4 ] = 0xbb ; g_dev_addr [ 5 ] = 0x0a ; /* Initialize the statistics package */ rc = stats_module_init (); assert ( rc == 0 ); /* Initialize the BLE LL */ rc = ble_ll_init ( 0 , 7 , 260 ); assert ( rc == 0 ); /* Initialize the application task. */ os_eventq_init ( &app_evq ); os_task_init ( &app_task , \"app\" , app_task_handler , NULL , 1 , OS_WAIT_FOREVER , app_stack , APP_STACK_SIZE ); /* Initialize the BLE host. */ rc = ble_hs_init ( &app_evq , NULL ); assert ( rc == 0 ); /* Start the OS */ os_start (); /* os start should never return. If it does, this should be an error */ assert ( 0 ); }","title":"Initialize the NimBLE host"},{"location":"network/ble/ini_stack/ble_ini_intro/","text":"Nimble stack initialization We are now going to explain how to set up your application to initialize the nimble stack and to get the basic stack, and its required modules, initialized and up and running. Note that the code shown here is an example of what is required for nimble stack operation; it is not intended to dictate to the developer exactly how to organize and set up your code. For example, the code sample shows modification of main.c in the application /src folder. The developer has the flexibility to organize the code as they see fit so this code does not need to reside in /src/main.c or in the main() function itself. The only possible issue is the order of some of the initializations. Where this order is important it is indicated in the sections covering stack initialization. A note about the code samples: the main() function in each code sample builds upon the previous example. However, code outside of main() shows only what we add for each step. The last code sample shows the entire main.c that we created. Let's start with a very basic main() function (shown below). This main() function is identical to the minimal version used in the Set up application introductory page. In this main() all we are doing is initializing the Mynewt OS and starting it. #include <assert.h> #include \"os/os.h\" int main ( void ) { /* Initialize OS */ os_init (); /* Start the OS */ os_start (); /* os start should never return. If it does, this should be an error */ assert ( 0 ); } The Nimble stack requires a number of packages to be initialized prior to being started. We are going to add these one by one to the application and describe each.","title":"toc"},{"location":"network/ble/ini_stack/ble_ini_intro/#nimble-stack-initialization","text":"We are now going to explain how to set up your application to initialize the nimble stack and to get the basic stack, and its required modules, initialized and up and running. Note that the code shown here is an example of what is required for nimble stack operation; it is not intended to dictate to the developer exactly how to organize and set up your code. For example, the code sample shows modification of main.c in the application /src folder. The developer has the flexibility to organize the code as they see fit so this code does not need to reside in /src/main.c or in the main() function itself. The only possible issue is the order of some of the initializations. Where this order is important it is indicated in the sections covering stack initialization. A note about the code samples: the main() function in each code sample builds upon the previous example. However, code outside of main() shows only what we add for each step. The last code sample shows the entire main.c that we created. Let's start with a very basic main() function (shown below). This main() function is identical to the minimal version used in the Set up application introductory page. In this main() all we are doing is initializing the Mynewt OS and starting it. #include <assert.h> #include \"os/os.h\" int main ( void ) { /* Initialize OS */ os_init (); /* Start the OS */ os_start (); /* os start should never return. If it does, this should be an error */ assert ( 0 ); } The Nimble stack requires a number of packages to be initialized prior to being started. We are going to add these one by one to the application and describe each.","title":"Nimble stack initialization"},{"location":"network/ble/ini_stack/ble_mempool/","text":"Create the System Memory Buffer Pool The Nimble stack allocates packet buffers (called mbufs) from the system memory buffer pool (msys). The system memory buffer pool and mbufs are described in the OS manual; we suggest reading that section in order to become familiar with mbufs if you are not already familiar with them. Note that the application itself (the unique application code that you are writing) does not need to use mbufs and none of the BLE host API exposed to the application developer uses them. However, the Nimble stack does require the existence of the system memory pool. Creating the memory pool and registering it with the system memory buffer pool can be a bit tricky the first time. However, using the template provided below it should be much easier. The header file /net/nimble/include/nimble/ble.h, which should be included in main.c, contains some MBUF macros that you will need to create the memory pool used by msys. The macro BLE_MBUF_PAYLOAD_SIZE defines the maximum amount of user payload, plus overhead, that a link layer BLE PDU can contain. The macro BLE_MBUF_MEMBLOCK_OVERHEAD is the amount of overhead required by the Nimble stack in each memory block used by the mbuf pool. The macro MBUF_NUM_MBUFS defines the number of mbufs in the mbuf pool and is defined locally. The user must determine, based on application requirements and platform memory size, how many mbufs are required. For example, if your application expects to have many simultaneous connections you may want to increase the size of the mbuf pool. In the example below, we assume you are only using a small number of active connections (2 to 3). A note about the size of the mbufs and BLE_MBUF_PAYLOAD_SIZE . Msys allows for multiple mbuf pools of various size. Currently, the Nimble stack requires that msys has an mbuf pool registered that can accommodate the maximum size BLE LL PDU. Thus, we only show the creation of one mbuf pool of maximum size mbufs which gets registered to the system mbuf memory pool. We plan on modifying the Nimble stack so that smaller mbufs can be used (to conserve memory) but at this point in time you cannot modify BLE_MBUF_PAYLOAD_SIZE . Furthermore, you cannot add a mbuf pool of smaller size elements to the msys pool as the msys code might then allocate a mbuf that is too small for the nimble stack. /* Create a mbuf pool of BLE mbufs */ #define MBUF_NUM_MBUFS (8) #define MBUF_BUF_SIZE OS_ALIGN(BLE_MBUF_PAYLOAD_SIZE, 4) #define MBUF_MEMBLOCK_SIZE (MBUF_BUF_SIZE + BLE_MBUF_MEMBLOCK_OVERHEAD) #define MBUF_MEMPOOL_SIZE OS_MEMPOOL_SIZE(MBUF_NUM_MBUFS, MBUF_MEMBLOCK_SIZE) struct os_mbuf_pool g_mbuf_pool ; struct os_mempool g_mbuf_mempool ; os_membuf_t g_mbuf_buffer [ MBUF_MEMPOOL_SIZE ]; int main ( void ) { int rc ; /* Initialize OS */ os_init (); /* Set cputime to count at 1 usec increments */ rc = cputime_init ( 1000000 ); assert ( rc == 0 ); /* Create memory pool for Nimble packets and register with Msys */ rc = os_mempool_init ( &g_mbuf_mempool , MBUF_NUM_MBUFS , MBUF_MEMBLOCK_SIZE , &g_mbuf_buffer [ 0 ], \"mbuf_pool\" ); assert ( rc == 0 ); rc = os_mbuf_pool_init ( &g_mbuf_pool , &g_mbuf_mempool , MBUF_MEMBLOCK_SIZE , MBUF_NUM_MBUFS ); assert ( rc == 0 ); rc = os_msys_register ( &g_mbuf_pool ); assert ( rc == 0 ); /* Start the OS */ os_start (); /* os start should never return. If it does, this should be an error */ assert ( 0 ); }","title":"Create mem pool"},{"location":"network/ble/ini_stack/ble_mempool/#create-the-system-memory-buffer-pool","text":"The Nimble stack allocates packet buffers (called mbufs) from the system memory buffer pool (msys). The system memory buffer pool and mbufs are described in the OS manual; we suggest reading that section in order to become familiar with mbufs if you are not already familiar with them. Note that the application itself (the unique application code that you are writing) does not need to use mbufs and none of the BLE host API exposed to the application developer uses them. However, the Nimble stack does require the existence of the system memory pool. Creating the memory pool and registering it with the system memory buffer pool can be a bit tricky the first time. However, using the template provided below it should be much easier. The header file /net/nimble/include/nimble/ble.h, which should be included in main.c, contains some MBUF macros that you will need to create the memory pool used by msys. The macro BLE_MBUF_PAYLOAD_SIZE defines the maximum amount of user payload, plus overhead, that a link layer BLE PDU can contain. The macro BLE_MBUF_MEMBLOCK_OVERHEAD is the amount of overhead required by the Nimble stack in each memory block used by the mbuf pool. The macro MBUF_NUM_MBUFS defines the number of mbufs in the mbuf pool and is defined locally. The user must determine, based on application requirements and platform memory size, how many mbufs are required. For example, if your application expects to have many simultaneous connections you may want to increase the size of the mbuf pool. In the example below, we assume you are only using a small number of active connections (2 to 3). A note about the size of the mbufs and BLE_MBUF_PAYLOAD_SIZE . Msys allows for multiple mbuf pools of various size. Currently, the Nimble stack requires that msys has an mbuf pool registered that can accommodate the maximum size BLE LL PDU. Thus, we only show the creation of one mbuf pool of maximum size mbufs which gets registered to the system mbuf memory pool. We plan on modifying the Nimble stack so that smaller mbufs can be used (to conserve memory) but at this point in time you cannot modify BLE_MBUF_PAYLOAD_SIZE . Furthermore, you cannot add a mbuf pool of smaller size elements to the msys pool as the msys code might then allocate a mbuf that is too small for the nimble stack. /* Create a mbuf pool of BLE mbufs */ #define MBUF_NUM_MBUFS (8) #define MBUF_BUF_SIZE OS_ALIGN(BLE_MBUF_PAYLOAD_SIZE, 4) #define MBUF_MEMBLOCK_SIZE (MBUF_BUF_SIZE + BLE_MBUF_MEMBLOCK_OVERHEAD) #define MBUF_MEMPOOL_SIZE OS_MEMPOOL_SIZE(MBUF_NUM_MBUFS, MBUF_MEMBLOCK_SIZE) struct os_mbuf_pool g_mbuf_pool ; struct os_mempool g_mbuf_mempool ; os_membuf_t g_mbuf_buffer [ MBUF_MEMPOOL_SIZE ]; int main ( void ) { int rc ; /* Initialize OS */ os_init (); /* Set cputime to count at 1 usec increments */ rc = cputime_init ( 1000000 ); assert ( rc == 0 ); /* Create memory pool for Nimble packets and register with Msys */ rc = os_mempool_init ( &g_mbuf_mempool , MBUF_NUM_MBUFS , MBUF_MEMBLOCK_SIZE , &g_mbuf_buffer [ 0 ], \"mbuf_pool\" ); assert ( rc == 0 ); rc = os_mbuf_pool_init ( &g_mbuf_pool , &g_mbuf_mempool , MBUF_MEMBLOCK_SIZE , MBUF_NUM_MBUFS ); assert ( rc == 0 ); rc = os_msys_register ( &g_mbuf_pool ); assert ( rc == 0 ); /* Start the OS */ os_start (); /* os start should never return. If it does, this should be an error */ assert ( 0 ); }","title":"Create the System Memory Buffer Pool"},{"location":"network/ble/ini_stack/ble_parent_ini/","text":"Create the host parent task The NimBLE stack requires an application task to function. One application task in particular is designated as the host parent task . In addition to application-specific work, the host parent task does work for NimBLE by processing events generated by the host. The process of creating an OS task is described in the Add Task tutorial . Priority: It is up to you which priority to use for the host parent task. Unlike the controller, the host does not have any strict timing requirements, so the priority should be based on the application's needs. In the below example, we use a priority of 1 . Stack size: The host parent task's stack needs to be sufficiently large to handle BLE operations. This depends on the set of BLE features your application uses, and on the specifics application callbacks that the stack is configured to use. A safe value is to use here is 300 words ; that is the value used in the below example. The parent task must do two things: Call ble_hs_start() before starting its task loop. Handle OS_EVENT_T_TIMER events within its task loop. The ble_hs_start() function is declared as follows: int ble_hs_start ( void ) The ble_hs_start() function causes the host to send a sequence of HCI commands to the controller. This sequence of commands is necessary for the host and controller to remain in sync. We add an application task to our example below. #include \"os/os.h\" /** Application task. */ static struct os_task app_task ; /** Application task event queue. */ static struct os_eventq app_evq ; /** Application task stack. */ #define APP_STACK_SIZE (OS_STACK_ALIGN(300)) static os_stack_t app_stack [ APP_STACK_SIZE ]; /** * Application task. */ static void app_task_handler ( void *arg ) { struct os_callout_func *cf ; struct os_event *ev ; int rc ; rc = ble_hs_start (); assert ( rc == 0 ); while ( 1 ) { ev = os_eventq_get ( &app_evq ); switch ( ev->ev_type ) { case OS_EVENT_T_TIMER : cf = ( struct os_callout_func * ) ev ; assert ( cf->cf_func ); cf->cf_func ( cf->cf_arg ); break ; default : assert ( 0 ); break ; } } } int main ( void ) { int rc ; /* Initialize OS */ os_init (); /* Set cputime to count at 1 usec increments */ rc = cputime_init ( 1000000 ); assert ( rc == 0 ); /* Create memory pool for Nimble packets and register with Msys */ rc = os_mempool_init ( &g_mbuf_mempool , MBUF_NUM_MBUFS , MBUF_MEMBLOCK_SIZE , &g_mbuf_buffer [ 0 ], \"mbuf_pool\" ); assert ( rc == 0 ); rc = os_mbuf_pool_init ( &g_mbuf_pool , &g_mbuf_mempool , MBUF_MEMBLOCK_SIZE , MBUF_NUM_MBUFS ); assert ( rc == 0 ); rc = os_msys_register ( &g_mbuf_pool ); assert ( rc == 0 ); /* Initialize our device address */ g_dev_addr [ 0 ] = 0x33 ; g_dev_addr [ 1 ] = 0x22 ; g_dev_addr [ 2 ] = 0x11 ; g_dev_addr [ 3 ] = 0xcc ; g_dev_addr [ 4 ] = 0xbb ; g_dev_addr [ 5 ] = 0x0a ; /* Initialize the statistics package */ rc = stats_module_init (); assert ( rc == 0 ); /* Initialize the BLE LL */ rc = ble_ll_init ( 0 , 7 , 260 ); assert ( rc == 0 ); /* Initialize the application task. */ os_eventq_init ( &app_evq ); os_task_init ( &app_task , \"app\" , app_task_handler , NULL , 1 , OS_WAIT_FOREVER , app_stack , APP_STACK_SIZE ); /* Start the OS */ os_start (); /* os start should never return. If it does, this should be an error */ assert ( 0 ); }","title":"Initialize parent task"},{"location":"network/ble/ini_stack/ble_parent_ini/#create-the-host-parent-task","text":"The NimBLE stack requires an application task to function. One application task in particular is designated as the host parent task . In addition to application-specific work, the host parent task does work for NimBLE by processing events generated by the host. The process of creating an OS task is described in the Add Task tutorial . Priority: It is up to you which priority to use for the host parent task. Unlike the controller, the host does not have any strict timing requirements, so the priority should be based on the application's needs. In the below example, we use a priority of 1 . Stack size: The host parent task's stack needs to be sufficiently large to handle BLE operations. This depends on the set of BLE features your application uses, and on the specifics application callbacks that the stack is configured to use. A safe value is to use here is 300 words ; that is the value used in the below example. The parent task must do two things: Call ble_hs_start() before starting its task loop. Handle OS_EVENT_T_TIMER events within its task loop. The ble_hs_start() function is declared as follows: int ble_hs_start ( void ) The ble_hs_start() function causes the host to send a sequence of HCI commands to the controller. This sequence of commands is necessary for the host and controller to remain in sync. We add an application task to our example below. #include \"os/os.h\" /** Application task. */ static struct os_task app_task ; /** Application task event queue. */ static struct os_eventq app_evq ; /** Application task stack. */ #define APP_STACK_SIZE (OS_STACK_ALIGN(300)) static os_stack_t app_stack [ APP_STACK_SIZE ]; /** * Application task. */ static void app_task_handler ( void *arg ) { struct os_callout_func *cf ; struct os_event *ev ; int rc ; rc = ble_hs_start (); assert ( rc == 0 ); while ( 1 ) { ev = os_eventq_get ( &app_evq ); switch ( ev->ev_type ) { case OS_EVENT_T_TIMER : cf = ( struct os_callout_func * ) ev ; assert ( cf->cf_func ); cf->cf_func ( cf->cf_arg ); break ; default : assert ( 0 ); break ; } } } int main ( void ) { int rc ; /* Initialize OS */ os_init (); /* Set cputime to count at 1 usec increments */ rc = cputime_init ( 1000000 ); assert ( rc == 0 ); /* Create memory pool for Nimble packets and register with Msys */ rc = os_mempool_init ( &g_mbuf_mempool , MBUF_NUM_MBUFS , MBUF_MEMBLOCK_SIZE , &g_mbuf_buffer [ 0 ], \"mbuf_pool\" ); assert ( rc == 0 ); rc = os_mbuf_pool_init ( &g_mbuf_pool , &g_mbuf_mempool , MBUF_MEMBLOCK_SIZE , MBUF_NUM_MBUFS ); assert ( rc == 0 ); rc = os_msys_register ( &g_mbuf_pool ); assert ( rc == 0 ); /* Initialize our device address */ g_dev_addr [ 0 ] = 0x33 ; g_dev_addr [ 1 ] = 0x22 ; g_dev_addr [ 2 ] = 0x11 ; g_dev_addr [ 3 ] = 0xcc ; g_dev_addr [ 4 ] = 0xbb ; g_dev_addr [ 5 ] = 0x0a ; /* Initialize the statistics package */ rc = stats_module_init (); assert ( rc == 0 ); /* Initialize the BLE LL */ rc = ble_ll_init ( 0 , 7 , 260 ); assert ( rc == 0 ); /* Initialize the application task. */ os_eventq_init ( &app_evq ); os_task_init ( &app_task , \"app\" , app_task_handler , NULL , 1 , OS_WAIT_FOREVER , app_stack , APP_STACK_SIZE ); /* Start the OS */ os_start (); /* os start should never return. If it does, this should be an error */ assert ( 0 ); }","title":"Create the host parent task"},{"location":"network/ble/ini_stack/ble_statpkg/","text":"Initialize the statistics package The NimBLE stack uses the statistics package. Initializing the statistics package is quite simple; all you need to do is enable it in your target's syscfg.yml configuration file and re-build your app. syscfg . vals: # Enable the shell task. SHELL_TASK : 1 STATS_CLI : 1","title":"Initialize stats pkg"},{"location":"network/ble/ini_stack/ble_statpkg/#initialize-the-statistics-package","text":"The NimBLE stack uses the statistics package. Initializing the statistics package is quite simple; all you need to do is enable it in your target's syscfg.yml configuration file and re-build your app. syscfg . vals: # Enable the shell task. SHELL_TASK : 1 STATS_CLI : 1","title":"Initialize the statistics package"},{"location":"news/article1/","text":"","title":"Article1"},{"location":"newt/newt_intro/","text":"Newt Tool Introduction Newt is a smart build and package management system for embedded contexts. It is a single tool that accomplishes both the following goals: source package management build, debug and install. Rationale In order for the Mynewt operating system to work well for constrained environments across the many different types of microcontroller applications (from doorbells to medical devices to power grids), a system is needed that lets you select which packages to install and which packages to build. The build systems for embedded devices are often fairly complicated and not well served for this purpose. For example, autoconf is designed for detecting system compatibility issues but not well suited when it comes to tasks like: Building for multiple targets Deciding what to build in and what not to build in Managing dependencies between components Fortunately, solutions addressing these very issues can be found in source package management systems in higher level languages such as Javascript (Node), Go, PHP and Ruby. We decided to fuse their source management systems with a make system built for embedded systems and create Newt. Build System A good build system must allow the user to take a few common steps while developing embedded applications: Generate full flash images Download debug images to a target board using a debugger Conditionally compile libraries & code based upon build settings Newt can read a directory tree, build a dependency tree, and emit the right build artifacts. An example newt source tree is in incubator-mynewt-blinky/develop: $ tree -L 3 . \u251c\u2500\u2500 DISCLAIMER \u251c\u2500\u2500 LICENSE \u251c\u2500\u2500 NOTICE \u251c\u2500\u2500 README.md \u251c\u2500\u2500 apps \u2502 \u2514\u2500\u2500 blinky \u2502 \u251c\u2500\u2500 pkg.yml \u2502 \u2514\u2500\u2500 src \u251c\u2500\u2500 project.yml \u2514\u2500\u2500 targets \u251c\u2500\u2500 my_blinky_sim \u2502 \u251c\u2500\u2500 pkg.yml \u2502 \u2514\u2500\u2500 target.yml \u2514\u2500\u2500 unittest \u251c\u2500\u2500 pkg.yml \u2514\u2500\u2500 target.yml 6 directories, 10 files When Newt sees a directory tree that contains a \"project.yml\" file, it is smart enough to recognize it as the base directory of a project, and automatically builds a package tree. It also recognizes two important package directories in the package tree - \"apps\" and \"targets\". More on these directories in Newt Theory of Ops . When Newt builds a target, it recursively resolves all package dependencies, and generates artifacts that are placed in the bin/targets/<target-name>/app/apps/<app-name> directory, where the bin directory is under the project base directory, target-name is the name of the target, and app-name is the name of the application. For our example my_blinky_sim is the name of the target and blinky is the name of the application. The blinky.elf executable is stored in the bin/targets/my_blinky_sim/app/apps/blinky directory as shown in the source tree: tree -L 6 bin/ bin/ \u2514\u2500\u2500 targets \u251c\u2500\u2500 my_blinky_sim \u2502 \u251c\u2500\u2500 app \u2502 \u2502 \u251c\u2500\u2500 apps \u2502 \u2502 \u2502 \u2514\u2500\u2500 blinky \u2502 \u2502 \u2502 \u251c\u2500\u2500 apps \u2502 \u2502 \u2502 \u251c\u2500\u2500 apps_blinky.a \u2502 \u2502 \u2502 \u251c\u2500\u2500 apps_blinky.a.cmd \u2502 \u2502 \u2502 \u251c\u2500\u2500 blinky.elf \u2502 \u2502 \u2502 \u251c\u2500\u2500 blinky.elf.cmd \u2502 \u2502 \u2502 \u251c\u2500\u2500 blinky.elf.dSYM \u2502 \u2502 \u2502 \u251c\u2500\u2500 blinky.elf.lst \u2502 \u2502 \u2502 \u2514\u2500\u2500 manifest.json \u2502 \u2502 \u251c\u2500\u2500 hw \u2502 \u2502 \u2502 \u251c\u2500\u2500 bsp \u2502 \u2502 \u2502 \u2502 \u2514\u2500\u2500 native \u2502 \u2502 \u2502 \u251c\u2500\u2500 drivers \u2502 \u2502 \u2502 \u2502 \u2514\u2500\u2500 uart \u2502 \u2502 \u2502 \u251c\u2500\u2500 hal \u2502 \u2502 \u2502 \u2502 \u251c\u2500\u2500 hw_hal.a \u2502 \u2502 \u2502 \u2502 \u251c\u2500\u2500 hw_hal.a.cmd \u2502 \u2502 \u2502 \u2502 \u2514\u2500\u2500 repos <snip> More operations using Newt Once a target has been built, Newt allows additional operations on the target. load : Download built target to board debug : Open debugger session to target size : Get size of target components create-image : Add image header to the binary image run : Build, create image, load, and finally open a debug session with the target target : Create, delete, configure, and query a target For more details on how Newt works, go to Newt - Theory of Operations . Source Management and Repositories The other major element of the Newt tool is the ability to create reusable source distributions from a collection of code. A project can be a reusable container of source code. In other words, projects can be versioned and redistributed, not packages. A project bundles together packages that are typically needed to work together in a product e.g. RTOS core, filesystem APIs, and networking stack. A project that has been made redistributable is known as a repository . Repositories can be added to your local project by adding them into your project.yml file. Here is an example of the blinky project's yml file which relies on apache-mynewt-core: $ more project.yml <snip> project.repositories: - apache-mynewt-core # Use github's distribution mechanism for core ASF libraries. # This provides mirroring automatically for us. # repository.apache-mynewt-core: type: github vers: 1-latest user: apache repo: incubator-mynewt-core When you specify this repository in the blinky's project file, you can then use the Newt tool to install dependencies: $ newt install Downloading repository description for apache-mynewt-core... success! Downloading repository incubator-mynewt-core (branch: develop) at https://github.com/apache/incubator-mynewt-core.git Cloning into '/var/folders/7l/7b3w9m4n2mg3sqmgw2q1b9p80000gn/T/newt-repo814721459'... remote: Counting objects: 17601, done. remote: Compressing objects: 100% (300/300), done. remote: Total 17601 (delta 142), reused 0 (delta 0), pack-reused 17284 Receiving objects: 100% (17601/17601), 6.09 MiB | 3.17 MiB/s, done. Resolving deltas: 100% (10347/10347), done. Checking connectivity... done. Repos successfully installed Newt will install this repository in the /repos directory. In the case of blinky, the directory structure ends up looking like: $ tree -L 2 . \u251c\u2500\u2500 DISCLAIMER \u251c\u2500\u2500 LICENSE \u251c\u2500\u2500 NOTICE \u251c\u2500\u2500 README.md \u251c\u2500\u2500 apps \u2502 \u2514\u2500\u2500 blinky \u251c\u2500\u2500 project.state \u251c\u2500\u2500 project.yml \u251c\u2500\u2500 repos \u2502 \u2514\u2500\u2500 apache-mynewt-core \u2514\u2500\u2500 targets \u251c\u2500\u2500 my_blinky_sim \u2514\u2500\u2500 unittest In order to reference the installed repositories in packages, the \"@\" notation should be specified in the repository specifier. As an example, the apps/blinky application has the following dependencies in its pkg.yml file. This tells the build system to look in the base directory of repos/apache-mynewt-core for the kernel/os , hw/hal , and sys/console/full packages. $ more apps/blinky/pkg.yml <snip> pkg.deps: - \"@apache-mynewt-core/kernel/os\" - \"@apache-mynewt-core/hw/hal\" - \"@apache-mynewt-core/sys/console/full\" Autocompletion in Bash Newt has the ability to autocomplete within bash . The following instructions allow MAC users to enable autocomplete within bash . Install the autocomplete tools for bash via brew install bash-completion Tell your shell to use newt for autocompletion of newt via complete -C \"newt complete\" newt . You can add this to your .bashrc or other init file to have it automatically set for all bash shells. Notes: Autocomplete will give you flag hints, but only if you type a '-'. Autocomplete will not give you completion hints for the flag arguments (those optional things after the flag like -l DEBUG ) Autocomplete uses newt to parse the project to find targets and libs.","title":"toc"},{"location":"newt/newt_intro/#newt-tool","text":"","title":"Newt Tool"},{"location":"newt/newt_intro/#introduction","text":"Newt is a smart build and package management system for embedded contexts. It is a single tool that accomplishes both the following goals: source package management build, debug and install.","title":"Introduction"},{"location":"newt/newt_intro/#rationale","text":"In order for the Mynewt operating system to work well for constrained environments across the many different types of microcontroller applications (from doorbells to medical devices to power grids), a system is needed that lets you select which packages to install and which packages to build. The build systems for embedded devices are often fairly complicated and not well served for this purpose. For example, autoconf is designed for detecting system compatibility issues but not well suited when it comes to tasks like: Building for multiple targets Deciding what to build in and what not to build in Managing dependencies between components Fortunately, solutions addressing these very issues can be found in source package management systems in higher level languages such as Javascript (Node), Go, PHP and Ruby. We decided to fuse their source management systems with a make system built for embedded systems and create Newt.","title":"Rationale"},{"location":"newt/newt_intro/#build-system","text":"A good build system must allow the user to take a few common steps while developing embedded applications: Generate full flash images Download debug images to a target board using a debugger Conditionally compile libraries & code based upon build settings Newt can read a directory tree, build a dependency tree, and emit the right build artifacts. An example newt source tree is in incubator-mynewt-blinky/develop: $ tree -L 3 . \u251c\u2500\u2500 DISCLAIMER \u251c\u2500\u2500 LICENSE \u251c\u2500\u2500 NOTICE \u251c\u2500\u2500 README.md \u251c\u2500\u2500 apps \u2502 \u2514\u2500\u2500 blinky \u2502 \u251c\u2500\u2500 pkg.yml \u2502 \u2514\u2500\u2500 src \u251c\u2500\u2500 project.yml \u2514\u2500\u2500 targets \u251c\u2500\u2500 my_blinky_sim \u2502 \u251c\u2500\u2500 pkg.yml \u2502 \u2514\u2500\u2500 target.yml \u2514\u2500\u2500 unittest \u251c\u2500\u2500 pkg.yml \u2514\u2500\u2500 target.yml 6 directories, 10 files When Newt sees a directory tree that contains a \"project.yml\" file, it is smart enough to recognize it as the base directory of a project, and automatically builds a package tree. It also recognizes two important package directories in the package tree - \"apps\" and \"targets\". More on these directories in Newt Theory of Ops . When Newt builds a target, it recursively resolves all package dependencies, and generates artifacts that are placed in the bin/targets/<target-name>/app/apps/<app-name> directory, where the bin directory is under the project base directory, target-name is the name of the target, and app-name is the name of the application. For our example my_blinky_sim is the name of the target and blinky is the name of the application. The blinky.elf executable is stored in the bin/targets/my_blinky_sim/app/apps/blinky directory as shown in the source tree: tree -L 6 bin/ bin/ \u2514\u2500\u2500 targets \u251c\u2500\u2500 my_blinky_sim \u2502 \u251c\u2500\u2500 app \u2502 \u2502 \u251c\u2500\u2500 apps \u2502 \u2502 \u2502 \u2514\u2500\u2500 blinky \u2502 \u2502 \u2502 \u251c\u2500\u2500 apps \u2502 \u2502 \u2502 \u251c\u2500\u2500 apps_blinky.a \u2502 \u2502 \u2502 \u251c\u2500\u2500 apps_blinky.a.cmd \u2502 \u2502 \u2502 \u251c\u2500\u2500 blinky.elf \u2502 \u2502 \u2502 \u251c\u2500\u2500 blinky.elf.cmd \u2502 \u2502 \u2502 \u251c\u2500\u2500 blinky.elf.dSYM \u2502 \u2502 \u2502 \u251c\u2500\u2500 blinky.elf.lst \u2502 \u2502 \u2502 \u2514\u2500\u2500 manifest.json \u2502 \u2502 \u251c\u2500\u2500 hw \u2502 \u2502 \u2502 \u251c\u2500\u2500 bsp \u2502 \u2502 \u2502 \u2502 \u2514\u2500\u2500 native \u2502 \u2502 \u2502 \u251c\u2500\u2500 drivers \u2502 \u2502 \u2502 \u2502 \u2514\u2500\u2500 uart \u2502 \u2502 \u2502 \u251c\u2500\u2500 hal \u2502 \u2502 \u2502 \u2502 \u251c\u2500\u2500 hw_hal.a \u2502 \u2502 \u2502 \u2502 \u251c\u2500\u2500 hw_hal.a.cmd \u2502 \u2502 \u2502 \u2502 \u2514\u2500\u2500 repos <snip>","title":"Build System"},{"location":"newt/newt_intro/#more-operations-using-newt","text":"Once a target has been built, Newt allows additional operations on the target. load : Download built target to board debug : Open debugger session to target size : Get size of target components create-image : Add image header to the binary image run : Build, create image, load, and finally open a debug session with the target target : Create, delete, configure, and query a target For more details on how Newt works, go to Newt - Theory of Operations .","title":"More operations using Newt"},{"location":"newt/newt_intro/#source-management-and-repositories","text":"The other major element of the Newt tool is the ability to create reusable source distributions from a collection of code. A project can be a reusable container of source code. In other words, projects can be versioned and redistributed, not packages. A project bundles together packages that are typically needed to work together in a product e.g. RTOS core, filesystem APIs, and networking stack. A project that has been made redistributable is known as a repository . Repositories can be added to your local project by adding them into your project.yml file. Here is an example of the blinky project's yml file which relies on apache-mynewt-core: $ more project.yml <snip> project.repositories: - apache-mynewt-core # Use github's distribution mechanism for core ASF libraries. # This provides mirroring automatically for us. # repository.apache-mynewt-core: type: github vers: 1-latest user: apache repo: incubator-mynewt-core When you specify this repository in the blinky's project file, you can then use the Newt tool to install dependencies: $ newt install Downloading repository description for apache-mynewt-core... success! Downloading repository incubator-mynewt-core (branch: develop) at https://github.com/apache/incubator-mynewt-core.git Cloning into '/var/folders/7l/7b3w9m4n2mg3sqmgw2q1b9p80000gn/T/newt-repo814721459'... remote: Counting objects: 17601, done. remote: Compressing objects: 100% (300/300), done. remote: Total 17601 (delta 142), reused 0 (delta 0), pack-reused 17284 Receiving objects: 100% (17601/17601), 6.09 MiB | 3.17 MiB/s, done. Resolving deltas: 100% (10347/10347), done. Checking connectivity... done. Repos successfully installed Newt will install this repository in the /repos directory. In the case of blinky, the directory structure ends up looking like: $ tree -L 2 . \u251c\u2500\u2500 DISCLAIMER \u251c\u2500\u2500 LICENSE \u251c\u2500\u2500 NOTICE \u251c\u2500\u2500 README.md \u251c\u2500\u2500 apps \u2502 \u2514\u2500\u2500 blinky \u251c\u2500\u2500 project.state \u251c\u2500\u2500 project.yml \u251c\u2500\u2500 repos \u2502 \u2514\u2500\u2500 apache-mynewt-core \u2514\u2500\u2500 targets \u251c\u2500\u2500 my_blinky_sim \u2514\u2500\u2500 unittest In order to reference the installed repositories in packages, the \"@\" notation should be specified in the repository specifier. As an example, the apps/blinky application has the following dependencies in its pkg.yml file. This tells the build system to look in the base directory of repos/apache-mynewt-core for the kernel/os , hw/hal , and sys/console/full packages. $ more apps/blinky/pkg.yml <snip> pkg.deps: - \"@apache-mynewt-core/kernel/os\" - \"@apache-mynewt-core/hw/hal\" - \"@apache-mynewt-core/sys/console/full\"","title":"Source Management and Repositories"},{"location":"newt/newt_intro/#autocompletion-in-bash","text":"Newt has the ability to autocomplete within bash . The following instructions allow MAC users to enable autocomplete within bash . Install the autocomplete tools for bash via brew install bash-completion Tell your shell to use newt for autocompletion of newt via complete -C \"newt complete\" newt . You can add this to your .bashrc or other init file to have it automatically set for all bash shells. Notes: Autocomplete will give you flag hints, but only if you type a '-'. Autocomplete will not give you completion hints for the flag arguments (those optional things after the flag like -l DEBUG ) Autocomplete uses newt to parse the project to find targets and libs.","title":"Autocompletion in Bash"},{"location":"newt/newt_operation/","text":"Newt Tool - Theory of Operations Newt has a fairly smart package manager that can read a directory tree, build a dependency tree, and emit the right build artifacts. Building dependencies Newt can read a directory tree, build a dependency tree, and emit the right build artifacts. An example newt source tree is in incubator-mynewt-blinky/develop: $ tree -L 3 . \u251c\u2500\u2500 DISCLAIMER \u251c\u2500\u2500 LICENSE \u251c\u2500\u2500 NOTICE \u251c\u2500\u2500 README.md \u251c\u2500\u2500 apps \u2502 \u2514\u2500\u2500 blinky \u2502 \u251c\u2500\u2500 pkg.yml \u2502 \u2514\u2500\u2500 src \u251c\u2500\u2500 project.yml \u2514\u2500\u2500 targets \u251c\u2500\u2500 my_blinky_sim \u2502 \u251c\u2500\u2500 pkg.yml \u2502 \u2514\u2500\u2500 target.yml \u2514\u2500\u2500 unittest \u251c\u2500\u2500 pkg.yml \u2514\u2500\u2500 target.yml 6 directories, 10 files When newt sees a directory tree that contains a \"project.yml\" file it knows that it is in the base directory of a project, and automatically builds a package tree. You can see that there are two essential package directories, \"apps\" and \"targets.\" \"apps\" Package Directory apps is where applications are stored, and applications are where the main() function is contained. The base project directory comes with one simple app called blinky in the apps directory. The core repository @apache-mynewt-core comes with many additional sample apps in its apps directory. At the time of this writing, there are several example BLE apps, the boot app, slinky app for using newt manager protocol, and more in that directory. @~/dev/myproj$ ls repos/apache-mynewt-core/apps/ blecent blesplit boot sensors_test splitty blehci bletest fat2native slinky test bleprph bletiny ffs2native slinky_oic testbench bleprph_oic bleuart ocf_sample spitest timtest Along with the targets directory, apps represents the top-level of the build tree for the particular project, and define the dependencies for the rest of the system. Mynewt users and developers can add their own apps to the project's apps directory. The app definition is contained in a pkg.yml file. For example, blinky's pkg.yml file is: $ more apps/blinky/pkg.yml <snip> pkg.name: apps/blinky pkg.type: app pkg.description: Basic example application which blinks an LED. pkg.author: \"Apache Mynewt <dev@mynewt.incubator.apache.org>\" pkg.homepage: \"http://mynewt.apache.org/\" pkg.keywords: pkg.deps: - \"@apache-mynewt-core/kernel/os\" - \"@apache-mynewt-core/hw/hal\" - \"@apache-mynewt-core/sys/console/full\" This file says that the name of the package is apps/blinky, and it depends on the kernel/os, hw/hal and sys/console/full` packages. NOTE: @apache-mynewt-core is a repository descriptor, and this will be covered in the \"repository\" section. \"targets\" Package Directory targets is where targets are stored, and each target is a collection of parameters that must be passed to newt in order to generate a reproducible build. Along with the apps directory, targets represents the top of the build tree. Any packages or parameters specified at the target level cascades down to all dependencies. Most targets consist of: app: The application to build bsp: The board support package to combine with that application build_profile: Either debug or optimized. The my_blinky_sim target that is included by default has the following settings: $ newt target show targets/my_blinky_sim app=apps/blinky bsp=@apache-mynewt-core/hw/bsp/native build_profile=debug $ ls targets/my_blinky_sim/ pkg.yml target.yml There are helper functions to aid the developer specify parameters for a target. vals : Displays all valid values for the specified parameter type (e.g. bsp for a target) target show : Displays the variable values for either a specific target or all targets defined for the project target set : Sets values for target variables In general, the three basic parameters of a target ( app , bsp , and build_profile ) are stored in the target's target.yml file in the targets/<target-name> directory, where target-name is the name of the target. You will also see a pkg.yml file in the same directory. Since targets are packages, a pkg.yml is expected. It contains typical package descriptors, dependencies, and additional parameters such as the following: Cflags: Any additional compiler flags you might want to specify to the build Aflags: Any additional assembler flags you might want to specify to the build Lflags: Any additional linker flags you might want to specify to the build You can also override the values of the system configuration settings that are defined by the packages that your target includes. You override the values in your target's syscfg.yml file (stored in the targets/<target-name> directory). You can use the newt target config show command to see the configuration settings and values for your target, and use the newt target set command to set the syscfg variable and override the configuration setting values. You can also use an editor to create your target's syscfg.yml file and add the setting values to the file. See System Configuration And Initialization for more information on system configuration settings. Resolving dependencies When newt builds a project, it will: find the top-level project.yml file recurse the packages in the package tree, and build a list of all source packages Newt then looks at the target that the user set, for example, blinky_sim: $ more targets/my_blinky_sim/ pkg.yml target.yml $ more targets/my_blinky_sim/target.yml ### Target: targets/my_blinky_sim target.app: \"apps/blinky\" target.bsp: \"@apache-mynewt-core/hw/bsp/native\" target.build_profile: \"debug\" The target specifies two major things: Application (target.app): The application to build Board Support Package (target.bsp): The board support package to build along with that application. Newt builds the dependency tree specified by all the packages. While building this tree, it does a few other things: Sets up the include paths for each package. Any package that depends on another package, automatically gets the include directories from the package it includes. Include directories in the newt structure must always be prefixed by the package name. For example, kernel/os has the following include tree and its include directory files contains the package name \"os\" before any header files. This is so in order to avoid any header file conflicts. $tree kernel/os/include kernel/os/include \u2514\u2500\u2500 os \u251c\u2500\u2500 arch \u2502 \u251c\u2500\u2500 cortex_m0 \u2502 \u2502 \u2514\u2500\u2500 os \u2502 \u2502 \u2514\u2500\u2500 os_arch.h \u2502 \u251c\u2500\u2500 cortex_m4 \u2502 \u2502 \u2514\u2500\u2500 os \u2502 \u2502 \u2514\u2500\u2500 os_arch.h \u2502 \u251c\u2500\u2500 mips \u2502 \u2502 \u2514\u2500\u2500 os \u2502 \u2502 \u2514\u2500\u2500 os_arch.h \u2502 \u251c\u2500\u2500 sim \u2502 \u2502 \u2514\u2500\u2500 os \u2502 \u2502 \u2514\u2500\u2500 os_arch.h \u2502 \u2514\u2500\u2500 sim-mips \u2502 \u2514\u2500\u2500 os \u2502 \u2514\u2500\u2500 os_arch.h \u251c\u2500\u2500 endian.h \u251c\u2500\u2500 os.h \u251c\u2500\u2500 os_callout.h \u251c\u2500\u2500 os_cfg.h \u251c\u2500\u2500 os_cputime.h \u251c\u2500\u2500 os_dev.h \u251c\u2500\u2500 os_eventq.h \u251c\u2500\u2500 os_fault.h \u251c\u2500\u2500 os_heap.h \u251c\u2500\u2500 os_malloc.h \u251c\u2500\u2500 os_mbuf.h \u251c\u2500\u2500 os_mempool.h \u251c\u2500\u2500 os_mutex.h \u251c\u2500\u2500 os_sanity.h \u251c\u2500\u2500 os_sched.h \u251c\u2500\u2500 os_sem.h \u251c\u2500\u2500 os_task.h \u251c\u2500\u2500 os_test.h \u251c\u2500\u2500 os_time.h \u2514\u2500\u2500 queue.h <snip> Validates API requirements. Packages can export APIs they implement, (i.e. pkg.api: hw-hal-impl), and other packages can require those APIs (i.e. pkg.req_api: hw-hal-impl). Reads and validates the configuration setting definitions and values from the package syscfg.yml files. It generates a syscfg.h header file that packages include in the source files in order to access the settings. It also generates a system initialization function to initialize the packages. See System Configuration And Initialization for more information. In order to properly resolve all dependencies in the build system, newt recursively processes the package dependencies until there are no new dependencies. And it builds a big list of all the packages that need to be build. Newt then goes through this package list, and builds every package into an archive file. NOTE: The newt tool generates compiler dependencies for all of these packages, and only rebuilds the packages whose dependencies have changed. Changes in package & project dependencies are also taken into account. It is smart, after all! Producing artifacts Once newt has built all the archive files, it then links the archive files together. The linkerscript to use is specified by the board support package (BSP.) The newt tool creates a bin directory under the base project directory, and places a target's build artifacts into the bin/targets/<target-name>/app/apps/<app-name> directory, where target-name is the name of the target and app-name is the name of the application. As an example, the blinky.elf executable for the blinky application defined by the my_blinky_sim target is stored in the bin/targets/my_blinky_sim/app/apps/blinky directory as shown in the following source tree: $tree -L 9 bin/ bin/ \u2514\u2500\u2500 targets \u251c\u2500\u2500 my_blinky_sim \u2502 \u251c\u2500\u2500 app \u2502 \u2502 \u251c\u2500\u2500 apps \u2502 \u2502 \u2502 \u2514\u2500\u2500 blinky \u2502 \u2502 \u2502 \u251c\u2500\u2500 apps \u2502 \u2502 \u2502 \u2502 \u2514\u2500\u2500 blinky \u2502 \u2502 \u2502 \u2502 \u2514\u2500\u2500 src \u2502 \u2502 \u2502 \u2502 \u251c\u2500\u2500 main.d \u2502 \u2502 \u2502 \u2502 \u251c\u2500\u2500 main.o \u2502 \u2502 \u2502 \u2502 \u2514\u2500\u2500 main.o.cmd \u2502 \u2502 \u2502 \u251c\u2500\u2500 apps_blinky.a \u2502 \u2502 \u2502 \u251c\u2500\u2500 apps_blinky.a.cmd \u2502 \u2502 \u2502 \u251c\u2500\u2500 blinky.elf \u2502 \u2502 \u2502 \u251c\u2500\u2500 blinky.elf.cmd \u2502 \u2502 \u2502 \u251c\u2500\u2500 blinky.elf.dSYM \u2502 \u2502 \u2502 \u2502 \u2514\u2500\u2500 Contents \u2502 \u2502 \u2502 \u2502 \u251c\u2500\u2500 Info.plist \u2502 \u2502 \u2502 \u2502 \u2514\u2500\u2500 Resources \u2502 \u2502 \u2502 \u2502 \u2514\u2500\u2500 DWARF \u2502 \u2502 \u2502 \u251c\u2500\u2500 blinky.elf.lst \u2502 \u2502 \u2502 \u2514\u2500\u2500 manifest.json \u2502 \u2502 \u251c\u2500\u2500 hw \u2502 \u2502 \u2502 \u251c\u2500\u2500 bsp \u2502 \u2502 \u2502 \u2502 \u2514\u2500\u2500 native \u2502 \u2502 \u2502 \u2502 \u251c\u2500\u2500 hw_bsp_native.a \u2502 \u2502 \u2502 \u2502 \u251c\u2500\u2500 hw_bsp_native.a.cmd \u2502 \u2502 \u2502 \u2502 \u2514\u2500\u2500 repos \u2502 \u2502 \u2502 \u2502 \u2514\u2500\u2500 apache-mynewt-core \u2502 \u2502 \u2502 \u2502 \u2514\u2500\u2500 hw <snip> As you can see, a number of files are generated: Archive File *.cmd: The command use to generate the object or archive file *.lst: The list file where symbols are located Note: The *.o object files that get put into the archive file are stored in the bin/targets/my_blinky_sim/app/apps/blinky/apps/blinky/src directory. Download/Debug Support Once a target has been build, there are a number of helper functions that work on the target. These are: load Download built target to board debug Open debugger session to target size Size of target components create-image Add image header to target binary run The equivalent of build, create-image, load, and debug on specified target target Create, delete, configure, and query a target load and debug handles driving GDB and the system debugger. These commands call out to scripts that are defined by the BSP. $ more repos/apache-mynewt-core/hw/bsp/nrf52dk/nrf52dk_debug.sh <snip> . $CORE_PATH/hw/scripts/jlink.sh FILE_NAME=$BIN_BASENAME.elf if [ $# -gt 2 ]; then SPLIT_ELF_NAME=$3.elf # TODO -- this magic number 0x42000 is the location of the second image # slot. we should either get this from a flash map file or somehow learn # this from the image itself EXTRA_GDB_CMDS=\"add-symbol-file $SPLIT_ELF_NAME 0x8000 -readnow\" fi JLINK_DEV=\"nRF52\" jlink_debug The idea is that every BSP will add support for the debugger environment for that board. That way common tools can be used across various development boards and kits.","title":"Newt Theory of Ops"},{"location":"newt/newt_operation/#newt-tool-theory-of-operations","text":"Newt has a fairly smart package manager that can read a directory tree, build a dependency tree, and emit the right build artifacts.","title":"Newt Tool - Theory of Operations"},{"location":"newt/newt_operation/#building-dependencies","text":"Newt can read a directory tree, build a dependency tree, and emit the right build artifacts. An example newt source tree is in incubator-mynewt-blinky/develop: $ tree -L 3 . \u251c\u2500\u2500 DISCLAIMER \u251c\u2500\u2500 LICENSE \u251c\u2500\u2500 NOTICE \u251c\u2500\u2500 README.md \u251c\u2500\u2500 apps \u2502 \u2514\u2500\u2500 blinky \u2502 \u251c\u2500\u2500 pkg.yml \u2502 \u2514\u2500\u2500 src \u251c\u2500\u2500 project.yml \u2514\u2500\u2500 targets \u251c\u2500\u2500 my_blinky_sim \u2502 \u251c\u2500\u2500 pkg.yml \u2502 \u2514\u2500\u2500 target.yml \u2514\u2500\u2500 unittest \u251c\u2500\u2500 pkg.yml \u2514\u2500\u2500 target.yml 6 directories, 10 files When newt sees a directory tree that contains a \"project.yml\" file it knows that it is in the base directory of a project, and automatically builds a package tree. You can see that there are two essential package directories, \"apps\" and \"targets.\"","title":"Building dependencies"},{"location":"newt/newt_operation/#apps-package-directory","text":"apps is where applications are stored, and applications are where the main() function is contained. The base project directory comes with one simple app called blinky in the apps directory. The core repository @apache-mynewt-core comes with many additional sample apps in its apps directory. At the time of this writing, there are several example BLE apps, the boot app, slinky app for using newt manager protocol, and more in that directory. @~/dev/myproj$ ls repos/apache-mynewt-core/apps/ blecent blesplit boot sensors_test splitty blehci bletest fat2native slinky test bleprph bletiny ffs2native slinky_oic testbench bleprph_oic bleuart ocf_sample spitest timtest Along with the targets directory, apps represents the top-level of the build tree for the particular project, and define the dependencies for the rest of the system. Mynewt users and developers can add their own apps to the project's apps directory. The app definition is contained in a pkg.yml file. For example, blinky's pkg.yml file is: $ more apps/blinky/pkg.yml <snip> pkg.name: apps/blinky pkg.type: app pkg.description: Basic example application which blinks an LED. pkg.author: \"Apache Mynewt <dev@mynewt.incubator.apache.org>\" pkg.homepage: \"http://mynewt.apache.org/\" pkg.keywords: pkg.deps: - \"@apache-mynewt-core/kernel/os\" - \"@apache-mynewt-core/hw/hal\" - \"@apache-mynewt-core/sys/console/full\" This file says that the name of the package is apps/blinky, and it depends on the kernel/os, hw/hal and sys/console/full` packages. NOTE: @apache-mynewt-core is a repository descriptor, and this will be covered in the \"repository\" section.","title":"\"apps\" Package Directory"},{"location":"newt/newt_operation/#targets-package-directory","text":"targets is where targets are stored, and each target is a collection of parameters that must be passed to newt in order to generate a reproducible build. Along with the apps directory, targets represents the top of the build tree. Any packages or parameters specified at the target level cascades down to all dependencies. Most targets consist of: app: The application to build bsp: The board support package to combine with that application build_profile: Either debug or optimized. The my_blinky_sim target that is included by default has the following settings: $ newt target show targets/my_blinky_sim app=apps/blinky bsp=@apache-mynewt-core/hw/bsp/native build_profile=debug $ ls targets/my_blinky_sim/ pkg.yml target.yml There are helper functions to aid the developer specify parameters for a target. vals : Displays all valid values for the specified parameter type (e.g. bsp for a target) target show : Displays the variable values for either a specific target or all targets defined for the project target set : Sets values for target variables In general, the three basic parameters of a target ( app , bsp , and build_profile ) are stored in the target's target.yml file in the targets/<target-name> directory, where target-name is the name of the target. You will also see a pkg.yml file in the same directory. Since targets are packages, a pkg.yml is expected. It contains typical package descriptors, dependencies, and additional parameters such as the following: Cflags: Any additional compiler flags you might want to specify to the build Aflags: Any additional assembler flags you might want to specify to the build Lflags: Any additional linker flags you might want to specify to the build You can also override the values of the system configuration settings that are defined by the packages that your target includes. You override the values in your target's syscfg.yml file (stored in the targets/<target-name> directory). You can use the newt target config show command to see the configuration settings and values for your target, and use the newt target set command to set the syscfg variable and override the configuration setting values. You can also use an editor to create your target's syscfg.yml file and add the setting values to the file. See System Configuration And Initialization for more information on system configuration settings.","title":"\"targets\" Package Directory"},{"location":"newt/newt_operation/#resolving-dependencies","text":"When newt builds a project, it will: find the top-level project.yml file recurse the packages in the package tree, and build a list of all source packages Newt then looks at the target that the user set, for example, blinky_sim: $ more targets/my_blinky_sim/ pkg.yml target.yml $ more targets/my_blinky_sim/target.yml ### Target: targets/my_blinky_sim target.app: \"apps/blinky\" target.bsp: \"@apache-mynewt-core/hw/bsp/native\" target.build_profile: \"debug\" The target specifies two major things: Application (target.app): The application to build Board Support Package (target.bsp): The board support package to build along with that application. Newt builds the dependency tree specified by all the packages. While building this tree, it does a few other things: Sets up the include paths for each package. Any package that depends on another package, automatically gets the include directories from the package it includes. Include directories in the newt structure must always be prefixed by the package name. For example, kernel/os has the following include tree and its include directory files contains the package name \"os\" before any header files. This is so in order to avoid any header file conflicts. $tree kernel/os/include kernel/os/include \u2514\u2500\u2500 os \u251c\u2500\u2500 arch \u2502 \u251c\u2500\u2500 cortex_m0 \u2502 \u2502 \u2514\u2500\u2500 os \u2502 \u2502 \u2514\u2500\u2500 os_arch.h \u2502 \u251c\u2500\u2500 cortex_m4 \u2502 \u2502 \u2514\u2500\u2500 os \u2502 \u2502 \u2514\u2500\u2500 os_arch.h \u2502 \u251c\u2500\u2500 mips \u2502 \u2502 \u2514\u2500\u2500 os \u2502 \u2502 \u2514\u2500\u2500 os_arch.h \u2502 \u251c\u2500\u2500 sim \u2502 \u2502 \u2514\u2500\u2500 os \u2502 \u2502 \u2514\u2500\u2500 os_arch.h \u2502 \u2514\u2500\u2500 sim-mips \u2502 \u2514\u2500\u2500 os \u2502 \u2514\u2500\u2500 os_arch.h \u251c\u2500\u2500 endian.h \u251c\u2500\u2500 os.h \u251c\u2500\u2500 os_callout.h \u251c\u2500\u2500 os_cfg.h \u251c\u2500\u2500 os_cputime.h \u251c\u2500\u2500 os_dev.h \u251c\u2500\u2500 os_eventq.h \u251c\u2500\u2500 os_fault.h \u251c\u2500\u2500 os_heap.h \u251c\u2500\u2500 os_malloc.h \u251c\u2500\u2500 os_mbuf.h \u251c\u2500\u2500 os_mempool.h \u251c\u2500\u2500 os_mutex.h \u251c\u2500\u2500 os_sanity.h \u251c\u2500\u2500 os_sched.h \u251c\u2500\u2500 os_sem.h \u251c\u2500\u2500 os_task.h \u251c\u2500\u2500 os_test.h \u251c\u2500\u2500 os_time.h \u2514\u2500\u2500 queue.h <snip> Validates API requirements. Packages can export APIs they implement, (i.e. pkg.api: hw-hal-impl), and other packages can require those APIs (i.e. pkg.req_api: hw-hal-impl). Reads and validates the configuration setting definitions and values from the package syscfg.yml files. It generates a syscfg.h header file that packages include in the source files in order to access the settings. It also generates a system initialization function to initialize the packages. See System Configuration And Initialization for more information. In order to properly resolve all dependencies in the build system, newt recursively processes the package dependencies until there are no new dependencies. And it builds a big list of all the packages that need to be build. Newt then goes through this package list, and builds every package into an archive file. NOTE: The newt tool generates compiler dependencies for all of these packages, and only rebuilds the packages whose dependencies have changed. Changes in package & project dependencies are also taken into account. It is smart, after all!","title":"Resolving dependencies"},{"location":"newt/newt_operation/#producing-artifacts","text":"Once newt has built all the archive files, it then links the archive files together. The linkerscript to use is specified by the board support package (BSP.) The newt tool creates a bin directory under the base project directory, and places a target's build artifacts into the bin/targets/<target-name>/app/apps/<app-name> directory, where target-name is the name of the target and app-name is the name of the application. As an example, the blinky.elf executable for the blinky application defined by the my_blinky_sim target is stored in the bin/targets/my_blinky_sim/app/apps/blinky directory as shown in the following source tree: $tree -L 9 bin/ bin/ \u2514\u2500\u2500 targets \u251c\u2500\u2500 my_blinky_sim \u2502 \u251c\u2500\u2500 app \u2502 \u2502 \u251c\u2500\u2500 apps \u2502 \u2502 \u2502 \u2514\u2500\u2500 blinky \u2502 \u2502 \u2502 \u251c\u2500\u2500 apps \u2502 \u2502 \u2502 \u2502 \u2514\u2500\u2500 blinky \u2502 \u2502 \u2502 \u2502 \u2514\u2500\u2500 src \u2502 \u2502 \u2502 \u2502 \u251c\u2500\u2500 main.d \u2502 \u2502 \u2502 \u2502 \u251c\u2500\u2500 main.o \u2502 \u2502 \u2502 \u2502 \u2514\u2500\u2500 main.o.cmd \u2502 \u2502 \u2502 \u251c\u2500\u2500 apps_blinky.a \u2502 \u2502 \u2502 \u251c\u2500\u2500 apps_blinky.a.cmd \u2502 \u2502 \u2502 \u251c\u2500\u2500 blinky.elf \u2502 \u2502 \u2502 \u251c\u2500\u2500 blinky.elf.cmd \u2502 \u2502 \u2502 \u251c\u2500\u2500 blinky.elf.dSYM \u2502 \u2502 \u2502 \u2502 \u2514\u2500\u2500 Contents \u2502 \u2502 \u2502 \u2502 \u251c\u2500\u2500 Info.plist \u2502 \u2502 \u2502 \u2502 \u2514\u2500\u2500 Resources \u2502 \u2502 \u2502 \u2502 \u2514\u2500\u2500 DWARF \u2502 \u2502 \u2502 \u251c\u2500\u2500 blinky.elf.lst \u2502 \u2502 \u2502 \u2514\u2500\u2500 manifest.json \u2502 \u2502 \u251c\u2500\u2500 hw \u2502 \u2502 \u2502 \u251c\u2500\u2500 bsp \u2502 \u2502 \u2502 \u2502 \u2514\u2500\u2500 native \u2502 \u2502 \u2502 \u2502 \u251c\u2500\u2500 hw_bsp_native.a \u2502 \u2502 \u2502 \u2502 \u251c\u2500\u2500 hw_bsp_native.a.cmd \u2502 \u2502 \u2502 \u2502 \u2514\u2500\u2500 repos \u2502 \u2502 \u2502 \u2502 \u2514\u2500\u2500 apache-mynewt-core \u2502 \u2502 \u2502 \u2502 \u2514\u2500\u2500 hw <snip> As you can see, a number of files are generated: Archive File *.cmd: The command use to generate the object or archive file *.lst: The list file where symbols are located Note: The *.o object files that get put into the archive file are stored in the bin/targets/my_blinky_sim/app/apps/blinky/apps/blinky/src directory.","title":"Producing artifacts"},{"location":"newt/newt_operation/#downloaddebug-support","text":"Once a target has been build, there are a number of helper functions that work on the target. These are: load Download built target to board debug Open debugger session to target size Size of target components create-image Add image header to target binary run The equivalent of build, create-image, load, and debug on specified target target Create, delete, configure, and query a target load and debug handles driving GDB and the system debugger. These commands call out to scripts that are defined by the BSP. $ more repos/apache-mynewt-core/hw/bsp/nrf52dk/nrf52dk_debug.sh <snip> . $CORE_PATH/hw/scripts/jlink.sh FILE_NAME=$BIN_BASENAME.elf if [ $# -gt 2 ]; then SPLIT_ELF_NAME=$3.elf # TODO -- this magic number 0x42000 is the location of the second image # slot. we should either get this from a flash map file or somehow learn # this from the image itself EXTRA_GDB_CMDS=\"add-symbol-file $SPLIT_ELF_NAME 0x8000 -readnow\" fi JLINK_DEV=\"nRF52\" jlink_debug The idea is that every BSP will add support for the debugger environment for that board. That way common tools can be used across various development boards and kits.","title":"Download/Debug Support"},{"location":"newt/newt_ops/","text":"Command Structure Just like verbs are actions in a sentence and adverbs modifiy verbs, so in the newt tool, commands are actions and flags modify actions. A command can have subcommands. Arguments to commands and subcommands, with appropriate flags, dictate the execution and result of a command. For instance, in the example below, the newt command has the subcommand target set in which the argument 'my_target1' is the target whose attribute, app , is set to '@apache-mynewt-core/hw/bsp/nrf52dk' newt target set my_target1 app=@apache-mynewt-core/hw/bsp/nrf52dk Global flags work uniformly across newt commands. Consider the flag -v, --verbose, It works both for command and subcommands, to generate verbose output. Likewise, the help flag -h or --help, to print helpful messsages. A command may additionally take flags specific to it. For example, the -n flag instructs newt debug not to start GDB from command line. newt debug <target-name> -n In addition to the Newt Tool Manual in docs, command-line help is available for each command (and subcommand), through the -h or --help options. newt target --help Commands to create, delete, configure, and query targets Usage: newt target [flags] newt target [command] Available Commands: config View or populate a target's system configuration copy Copy target create Create a target delete Delete target dep View target's dependency graph revdep View target's reverse-dependency graph set Set target configuration variable show View target configuration variables Global Flags: -h, --help Help for newt commands -j, --jobs int Number of concurrent build jobs (default 8) -l, --loglevel string Log level (default \"WARN\") -o, --outfile string Filename to tee output to -q, --quiet Be quiet; only display error output -s, --silent Be silent; don't output anything -v, --verbose Enable verbose output when executing commands Use \"newt target [command] --help\" for more information about a command.","title":"toc"},{"location":"newt/newt_ops/#command-structure","text":"Just like verbs are actions in a sentence and adverbs modifiy verbs, so in the newt tool, commands are actions and flags modify actions. A command can have subcommands. Arguments to commands and subcommands, with appropriate flags, dictate the execution and result of a command. For instance, in the example below, the newt command has the subcommand target set in which the argument 'my_target1' is the target whose attribute, app , is set to '@apache-mynewt-core/hw/bsp/nrf52dk' newt target set my_target1 app=@apache-mynewt-core/hw/bsp/nrf52dk Global flags work uniformly across newt commands. Consider the flag -v, --verbose, It works both for command and subcommands, to generate verbose output. Likewise, the help flag -h or --help, to print helpful messsages. A command may additionally take flags specific to it. For example, the -n flag instructs newt debug not to start GDB from command line. newt debug <target-name> -n In addition to the Newt Tool Manual in docs, command-line help is available for each command (and subcommand), through the -h or --help options. newt target --help Commands to create, delete, configure, and query targets Usage: newt target [flags] newt target [command] Available Commands: config View or populate a target's system configuration copy Copy target create Create a target delete Delete target dep View target's dependency graph revdep View target's reverse-dependency graph set Set target configuration variable show View target configuration variables Global Flags: -h, --help Help for newt commands -j, --jobs int Number of concurrent build jobs (default 8) -l, --loglevel string Log level (default \"WARN\") -o, --outfile string Filename to tee output to -q, --quiet Be quiet; only display error output -s, --silent Be silent; don't output anything -v, --verbose Enable verbose output when executing commands Use \"newt target [command] --help\" for more information about a command.","title":"Command Structure"},{"location":"newt/command_list/newt_build/","text":"newt build Build one or more targets. Usage: newt build <target-name> [target_name ...] [flags] Global Flags: -h, --help Help for newt commands -j, --jobs int Number of concurrent build jobs (default 8) -l, --loglevel string Log level (default \"WARN\") -o, --outfile string Filename to tee output to -q, --quiet Be quiet; only display error output -s, --silent Be silent; don't output anything -v, --verbose Enable verbose output when executing commands Description Compiles, links, and builds an ELF binary for the target named <target-name>. It builds an ELF file for the application specified by the app variable for the target-name target. The image can be loaded and run on the hardware specified by the bsp variable for the target. The command creates the 'bin/' directory under the project's base directory (that the newt new command created) and stores the executable in the 'bin/targets/<target-name>/app/apps/<app-name>' directory. You can specify a list of target names, separated by a space, to build multiple targets. Examples Sub-command Usage Explanation newt build my_blinky_sim Builds an executable for the my_blinky_sim target. For example, if the my_blinky_sim target has app set to apps/blinky , you will find the generated .elf, .a, and .lst files in the 'bin/targets/my_blinky_sim/app/apps/blinky' directory. newt build my_blinky_sim myble Builds the images for the applications defined by the my_blinky_sim and myble targets.","title":"newt build"},{"location":"newt/command_list/newt_build/#newt-build","text":"Build one or more targets.","title":"newt build "},{"location":"newt/command_list/newt_build/#usage","text":"newt build <target-name> [target_name ...] [flags]","title":"Usage:"},{"location":"newt/command_list/newt_build/#global-flags","text":"-h, --help Help for newt commands -j, --jobs int Number of concurrent build jobs (default 8) -l, --loglevel string Log level (default \"WARN\") -o, --outfile string Filename to tee output to -q, --quiet Be quiet; only display error output -s, --silent Be silent; don't output anything -v, --verbose Enable verbose output when executing commands","title":"Global Flags:"},{"location":"newt/command_list/newt_build/#description","text":"Compiles, links, and builds an ELF binary for the target named <target-name>. It builds an ELF file for the application specified by the app variable for the target-name target. The image can be loaded and run on the hardware specified by the bsp variable for the target. The command creates the 'bin/' directory under the project's base directory (that the newt new command created) and stores the executable in the 'bin/targets/<target-name>/app/apps/<app-name>' directory. You can specify a list of target names, separated by a space, to build multiple targets.","title":"Description"},{"location":"newt/command_list/newt_build/#examples","text":"Sub-command Usage Explanation newt build my_blinky_sim Builds an executable for the my_blinky_sim target. For example, if the my_blinky_sim target has app set to apps/blinky , you will find the generated .elf, .a, and .lst files in the 'bin/targets/my_blinky_sim/app/apps/blinky' directory. newt build my_blinky_sim myble Builds the images for the applications defined by the my_blinky_sim and myble targets.","title":"Examples"},{"location":"newt/command_list/newt_clean/","text":"newt clean Delete build artifacts for one or more targets. Usage: newt clean <target-name> [target-name...] | all [flags] Global Flags: -h, --help Help for newt commands -j, --jobs int Number of concurrent build jobs (default 8) -l, --loglevel string Log level (default \"WARN\") -o, --outfile string Filename to tee output to -q, --quiet Be quiet; only display error output -s, --silent Be silent; don't output anything -v, --verbose Enable verbose output when executing commands Description Deletes all the build artifacts generated for the target-name target. It does not delete the target definition. You can specify a list of targets, separated by a space, to delete the artifacts for multiple targets, or specify all to delete the artifacts for all targets. Examples Sub-command Usage Explanation newt clean myble Deletes the 'bin/targets/myble' directory where all the build artifacts generated from the myble target build are stored. newt clean my_blinky_sim myble Deletes the 'bin/targets/my_blinky_sim' and the 'bin/targets/myble' directories where all the artifacts generated from the my_blinky_sim and myble target builds are stored. newt clean all Removes the artifacts for all target builds. Deletes the top level 'bin' directory.","title":"newt clean"},{"location":"newt/command_list/newt_clean/#newt-clean","text":"Delete build artifacts for one or more targets.","title":"newt clean "},{"location":"newt/command_list/newt_clean/#usage","text":"newt clean <target-name> [target-name...] | all [flags]","title":"Usage:"},{"location":"newt/command_list/newt_clean/#global-flags","text":"-h, --help Help for newt commands -j, --jobs int Number of concurrent build jobs (default 8) -l, --loglevel string Log level (default \"WARN\") -o, --outfile string Filename to tee output to -q, --quiet Be quiet; only display error output -s, --silent Be silent; don't output anything -v, --verbose Enable verbose output when executing commands","title":"Global Flags:"},{"location":"newt/command_list/newt_clean/#description","text":"Deletes all the build artifacts generated for the target-name target. It does not delete the target definition. You can specify a list of targets, separated by a space, to delete the artifacts for multiple targets, or specify all to delete the artifacts for all targets.","title":"Description"},{"location":"newt/command_list/newt_clean/#examples","text":"Sub-command Usage Explanation newt clean myble Deletes the 'bin/targets/myble' directory where all the build artifacts generated from the myble target build are stored. newt clean my_blinky_sim myble Deletes the 'bin/targets/my_blinky_sim' and the 'bin/targets/myble' directories where all the artifacts generated from the my_blinky_sim and myble target builds are stored. newt clean all Removes the artifacts for all target builds. Deletes the top level 'bin' directory.","title":"Examples"},{"location":"newt/command_list/newt_complete/","text":"newt complete Performs bash autocompletion using tab. It is not intended to be called directly from the command line. Install bash autocompletion $ brew install bash-completion Updating Homebrew... <snip> Bash completion has been installed to: /usr/local/etc/bash_completion.d ==> Summary \ud83c\udf7a /usr/local/Cellar/bash-completion/1.3_1: 189 files, 607.8K Enable autocompletion for newt $ complete -C \"newt complete\" newt Usage Hit tab and see possible completion options or completed command. $ newt target s set show $ newt target show","title":"Newt complete"},{"location":"newt/command_list/newt_complete/#newt-complete","text":"Performs bash autocompletion using tab. It is not intended to be called directly from the command line.","title":"newt complete "},{"location":"newt/command_list/newt_complete/#install-bash-autocompletion","text":"$ brew install bash-completion Updating Homebrew... <snip> Bash completion has been installed to: /usr/local/etc/bash_completion.d ==> Summary \ud83c\udf7a /usr/local/Cellar/bash-completion/1.3_1: 189 files, 607.8K","title":"Install bash autocompletion"},{"location":"newt/command_list/newt_complete/#enable-autocompletion-for-newt","text":"$ complete -C \"newt complete\" newt","title":"Enable autocompletion for newt"},{"location":"newt/command_list/newt_complete/#usage","text":"Hit tab and see possible completion options or completed command. $ newt target s set show $ newt target show","title":"Usage"},{"location":"newt/command_list/newt_create_image/","text":"newt create-image Create and sign an image by adding an image header to the binary file created for a target. Version number in the header is set to <version>. To sign an image provide a .pem file for the signing-key and an optional key-id. Usage: newt create-image <target-name> <version> [signing-key [key-id]][flags] Global Flags: -h, --help Help for newt commands -j, --jobs int Number of concurrent build jobs (default 8) -l, --loglevel string Log level (default \"WARN\") -o, --outfile string Filename to tee output to -q, --quiet Be quiet; only display error output -s, --silent Be silent; don't output anything -v, --verbose Enable verbose output when executing commands Description Adds an image header to the created binary file for the target-name target. The image version is set to version . It creates a <app-name>.img file for the image, where app-name is the value specified in the target app variable, and stores the file in the '/bin/targets/<target-name>/app/apps/<app-name>/' directory. A manifest.json build manifest file is also generated in the same directory. This build manifest contains information such as build time, version, image name, a hash to identify the image, packages actually used to create the build, and the target for which the image is built. To sign an image, provide a .pem file for the signing-key and an optional key-id . key-id must be a value between 0-255. Examples Sub-command Usage Explanation newt create-image myble2 1.0.1.0 Creates an image for target myble2 and assigns it version 1.0.1.0 . For the following target definition: targets/myble2 app=@apache-mynewt-core/apps/bletiny bsp=@apache-mynewt-core/hw/bsp/nrf52pdk build_profile=optimized cflags=-DSTATS_NAME_ENABLE the created image is 'bin/targets/myble2/app/apps/bletiny/bletiny.img' and the manifest is 'bin/targets/myble2/app/apps/bletiny/manifest.json' newt create-image myble2 1.0.1.0 private.pem Creates an image for target myble2 and assigns it the version 1.0.1.0 . Signs the image using private key specified by the private.pem file.","title":"newt create-image"},{"location":"newt/command_list/newt_create_image/#newt-create-image","text":"Create and sign an image by adding an image header to the binary file created for a target. Version number in the header is set to <version>. To sign an image provide a .pem file for the signing-key and an optional key-id.","title":"newt create-image "},{"location":"newt/command_list/newt_create_image/#usage","text":"newt create-image <target-name> <version> [signing-key [key-id]][flags]","title":"Usage:"},{"location":"newt/command_list/newt_create_image/#global-flags","text":"-h, --help Help for newt commands -j, --jobs int Number of concurrent build jobs (default 8) -l, --loglevel string Log level (default \"WARN\") -o, --outfile string Filename to tee output to -q, --quiet Be quiet; only display error output -s, --silent Be silent; don't output anything -v, --verbose Enable verbose output when executing commands","title":"Global Flags:"},{"location":"newt/command_list/newt_create_image/#description","text":"Adds an image header to the created binary file for the target-name target. The image version is set to version . It creates a <app-name>.img file for the image, where app-name is the value specified in the target app variable, and stores the file in the '/bin/targets/<target-name>/app/apps/<app-name>/' directory. A manifest.json build manifest file is also generated in the same directory. This build manifest contains information such as build time, version, image name, a hash to identify the image, packages actually used to create the build, and the target for which the image is built. To sign an image, provide a .pem file for the signing-key and an optional key-id . key-id must be a value between 0-255.","title":"Description"},{"location":"newt/command_list/newt_create_image/#examples","text":"Sub-command Usage Explanation newt create-image myble2 1.0.1.0 Creates an image for target myble2 and assigns it version 1.0.1.0 . For the following target definition: targets/myble2 app=@apache-mynewt-core/apps/bletiny bsp=@apache-mynewt-core/hw/bsp/nrf52pdk build_profile=optimized cflags=-DSTATS_NAME_ENABLE the created image is 'bin/targets/myble2/app/apps/bletiny/bletiny.img' and the manifest is 'bin/targets/myble2/app/apps/bletiny/manifest.json' newt create-image myble2 1.0.1.0 private.pem Creates an image for target myble2 and assigns it the version 1.0.1.0 . Signs the image using private key specified by the private.pem file.","title":"Examples"},{"location":"newt/command_list/newt_debug/","text":"newt debug Open a debugger session to a target. Usage: newt debug <target-name> [flag] Flags: --extrajtagcmd string Extra commands to send to JTAG software -n, --noGDB Do not start GDB from command line Global Flags: -h, --help Help for newt commands -j, --jobs int Number of concurrent build jobs (default 8) -l, --loglevel string Log level (default \"WARN\") -o, --outfile string Filename to tee output to -q, --quiet Be quiet; only display error output -s, --silent Be silent; don't output anything -v, --verbose Enable verbose output when executing commands Description Opens a debugger session to the image built for the <target-name> target. Examples Sub-command Usage Explanation newt debug myble2 Opens a J-Link connection and starts a GNU gdb session to debug bin/targets/myble2/app/apps/bletiny/bletiny.elf when the target is as follows: targets/myble2 app=@apache-mynewt-core/apps/bletiny bsp=@apache-mynewt-core/hw/bsp/nrf52pdk build_profile=optimized cflags=-DSTATS_NAME_ENABLE newt debug myble2 -n Opens a J-Link connection bin/targets/myble2/app/apps/bletiny/bletiny.elf but do not start GDB on the command line.","title":"newt debug"},{"location":"newt/command_list/newt_debug/#newt-debug","text":"Open a debugger session to a target.","title":"newt debug "},{"location":"newt/command_list/newt_debug/#usage","text":"newt debug <target-name> [flag]","title":"Usage:"},{"location":"newt/command_list/newt_debug/#flags","text":"--extrajtagcmd string Extra commands to send to JTAG software -n, --noGDB Do not start GDB from command line","title":"Flags:"},{"location":"newt/command_list/newt_debug/#global-flags","text":"-h, --help Help for newt commands -j, --jobs int Number of concurrent build jobs (default 8) -l, --loglevel string Log level (default \"WARN\") -o, --outfile string Filename to tee output to -q, --quiet Be quiet; only display error output -s, --silent Be silent; don't output anything -v, --verbose Enable verbose output when executing commands","title":"Global Flags:"},{"location":"newt/command_list/newt_debug/#description","text":"Opens a debugger session to the image built for the <target-name> target.","title":"Description"},{"location":"newt/command_list/newt_debug/#examples","text":"Sub-command Usage Explanation newt debug myble2 Opens a J-Link connection and starts a GNU gdb session to debug bin/targets/myble2/app/apps/bletiny/bletiny.elf when the target is as follows: targets/myble2 app=@apache-mynewt-core/apps/bletiny bsp=@apache-mynewt-core/hw/bsp/nrf52pdk build_profile=optimized cflags=-DSTATS_NAME_ENABLE newt debug myble2 -n Opens a J-Link connection bin/targets/myble2/app/apps/bletiny/bletiny.elf but do not start GDB on the command line.","title":"Examples"},{"location":"newt/command_list/newt_help/","text":"newt help Display the help text for the newt command line tool: Newt allows you to create your own embedded application based on the Mynewt operating system. Newt provides both build and package management in a single tool, which allows you to compose an embedded application, and set of projects, and then build the necessary artifacts from those projects. For more information on the Mynewt operating system, please visit https://mynewt.apache.org/. Usage: newt help [command] Global Flags: -h, --help Help for newt commands -j, --jobs int Number of concurrent build jobs (default 8) -l, --loglevel string Log level (default \"WARN\") -o, --outfile string Filename to tee output to -q, --quiet Be quiet; only display error output -s, --silent Be silent; don't output anything -v, --verbose Enable verbose output when executing commands Available Commands: build Build one or more targets clean Delete build artifacts for one or more targets create-image Add image header to target binary debug Open debugger session to target info Show project info install Install project dependencies load Load built target to board mfg Manufacturing flash image commands new Create a new project pkg Create and manage packages in the current workspace run build/create-image/download/debug <target> size Size of target components sync Synchronize project dependencies target Command for manipulating targets test Executes unit tests for one or more packages upgrade Upgrade project dependencies vals Display valid values for the specified element type(s) version Display the Newt version number Examples Sub-command Usage Explanation newt help target Displays the help text for the newt target command newt help Displays the help text for newt tool","title":"newt help"},{"location":"newt/command_list/newt_help/#newt-help","text":"Display the help text for the newt command line tool: Newt allows you to create your own embedded application based on the Mynewt operating system. Newt provides both build and package management in a single tool, which allows you to compose an embedded application, and set of projects, and then build the necessary artifacts from those projects. For more information on the Mynewt operating system, please visit https://mynewt.apache.org/.","title":"newt help "},{"location":"newt/command_list/newt_help/#usage","text":"newt help [command]","title":"Usage:"},{"location":"newt/command_list/newt_help/#global-flags","text":"-h, --help Help for newt commands -j, --jobs int Number of concurrent build jobs (default 8) -l, --loglevel string Log level (default \"WARN\") -o, --outfile string Filename to tee output to -q, --quiet Be quiet; only display error output -s, --silent Be silent; don't output anything -v, --verbose Enable verbose output when executing commands","title":"Global Flags:"},{"location":"newt/command_list/newt_help/#available-commands","text":"build Build one or more targets clean Delete build artifacts for one or more targets create-image Add image header to target binary debug Open debugger session to target info Show project info install Install project dependencies load Load built target to board mfg Manufacturing flash image commands new Create a new project pkg Create and manage packages in the current workspace run build/create-image/download/debug <target> size Size of target components sync Synchronize project dependencies target Command for manipulating targets test Executes unit tests for one or more packages upgrade Upgrade project dependencies vals Display valid values for the specified element type(s) version Display the Newt version number","title":"Available Commands:"},{"location":"newt/command_list/newt_help/#examples","text":"Sub-command Usage Explanation newt help target Displays the help text for the newt target command newt help Displays the help text for newt tool","title":"Examples"},{"location":"newt/command_list/newt_info/","text":"newt info Show information about the current project. Usage: newt info [flags] Global Flags: -h, --help Help for newt commands -j, --jobs int Number of concurrent build jobs (default 8) -l, --loglevel string Log level (default \"WARN\") -o, --outfile string Filename to tee output to -q, --quiet Be quiet; only display error output -s, --silent Be silent; don't output anything -v, --verbose Enable verbose output when executing commands Description Displays the repositories in the current project (the local as well as all the external repositories fetched). It also displays the packages in the local repository.","title":"newt info"},{"location":"newt/command_list/newt_info/#newt-info","text":"Show information about the current project.","title":"newt info "},{"location":"newt/command_list/newt_info/#usage","text":"newt info [flags]","title":"Usage:"},{"location":"newt/command_list/newt_info/#global-flags","text":"-h, --help Help for newt commands -j, --jobs int Number of concurrent build jobs (default 8) -l, --loglevel string Log level (default \"WARN\") -o, --outfile string Filename to tee output to -q, --quiet Be quiet; only display error output -s, --silent Be silent; don't output anything -v, --verbose Enable verbose output when executing commands","title":"Global Flags:"},{"location":"newt/command_list/newt_info/#description","text":"Displays the repositories in the current project (the local as well as all the external repositories fetched). It also displays the packages in the local repository.","title":"Description"},{"location":"newt/command_list/newt_install/","text":"newt install Install project dependencies. Usage: newt install [flags] Flags: -f, --force Force install of the repositories in project, regardless of what exists in repos directory Global Flags: -h, --help Help for newt commands -j, --jobs int Number of concurrent build jobs (default 8) -l, --loglevel string Log level (default \"WARN\") -o, --outfile string Filename to tee output to -q, --quiet Be quiet; only display error output -s, --silent Be silent; don't output anything -v, --verbose Enable verbose output when executing commands Description This command downloads the description for all the repositories specified in the project.yml file for the current project, and installs the correct versions of all the packages specified by the project dependencies. You must run this command from within the current project directory. (Remember to cd into this project directory after you use newt new to create this project before you run newt install .)","title":"newt install"},{"location":"newt/command_list/newt_install/#newt-install","text":"Install project dependencies.","title":"newt install "},{"location":"newt/command_list/newt_install/#usage","text":"newt install [flags]","title":"Usage:"},{"location":"newt/command_list/newt_install/#flags","text":"-f, --force Force install of the repositories in project, regardless of what exists in repos directory","title":"Flags:"},{"location":"newt/command_list/newt_install/#global-flags","text":"-h, --help Help for newt commands -j, --jobs int Number of concurrent build jobs (default 8) -l, --loglevel string Log level (default \"WARN\") -o, --outfile string Filename to tee output to -q, --quiet Be quiet; only display error output -s, --silent Be silent; don't output anything -v, --verbose Enable verbose output when executing commands","title":"Global Flags:"},{"location":"newt/command_list/newt_install/#description","text":"This command downloads the description for all the repositories specified in the project.yml file for the current project, and installs the correct versions of all the packages specified by the project dependencies. You must run this command from within the current project directory. (Remember to cd into this project directory after you use newt new to create this project before you run newt install .)","title":"Description"},{"location":"newt/command_list/newt_load/","text":"newt load Load application image onto the board for a target. Usage: newt load <target-name> [flags] Flags: --extrajtagcmd string Extra commands to send to JTAG software Global Flags: -h, --help Help for newt commands -j, --jobs int Number of concurrent build jobs (default 8) -l, --loglevel string Log level (default \"WARN\") -o, --outfile string Filename to tee output to -q, --quiet Be quiet; only display error output -s, --silent Be silent; don't output anything -v, --verbose Enable verbose output when executing commands Description Uses download scripts to automatically load, onto the connected board, the image built for the app defined by the target-name target If the wrong board is connected or the target definition is incorrect (i.e. the wrong values are given for bsp or app), the command will fail with error messages such as Can not connect to J-Link via USB or Unspecified error -1 .","title":"newt load"},{"location":"newt/command_list/newt_load/#newt-load","text":"Load application image onto the board for a target.","title":"newt load "},{"location":"newt/command_list/newt_load/#usage","text":"newt load <target-name> [flags]","title":"Usage:"},{"location":"newt/command_list/newt_load/#flags","text":"--extrajtagcmd string Extra commands to send to JTAG software","title":"Flags:"},{"location":"newt/command_list/newt_load/#global-flags","text":"-h, --help Help for newt commands -j, --jobs int Number of concurrent build jobs (default 8) -l, --loglevel string Log level (default \"WARN\") -o, --outfile string Filename to tee output to -q, --quiet Be quiet; only display error output -s, --silent Be silent; don't output anything -v, --verbose Enable verbose output when executing commands","title":"Global Flags:"},{"location":"newt/command_list/newt_load/#description","text":"Uses download scripts to automatically load, onto the connected board, the image built for the app defined by the target-name target If the wrong board is connected or the target definition is incorrect (i.e. the wrong values are given for bsp or app), the command will fail with error messages such as Can not connect to J-Link via USB or Unspecified error -1 .","title":"Description"},{"location":"newt/command_list/newt_mfg/","text":"newt mfg Commands to create, build, and upload manufacturing image. Usage: newt mfg [flags] newt mfg [command] Available Commands: create Create a manufacturing flash image deploy Build and upload a manufacturing image (build + load) load Load a manufacturing flash image onto a device Global Flags: -h, --help Help for newt commands -j, --jobs int Number of concurrent build jobs (default 8) -l, --loglevel string Log level (default \"WARN\") -o, --outfile string Filename to tee output to -q, --quiet Be quiet; only display error output -s, --silent Be silent; don't output anything -v, --verbose Enable verbose output when executing commands Description Sub-command Explanation create A manufacturing image specifies 1) a boot loader target, and 2) one or more image targets. Assuming the manufacturing entity has been created and defined in the mfgs/<mfg image name>/ package (see Examples below), this command collects the manufacturing related files in the newly created bin/mfgs/<mfg image name> directory. The collection includes manifests with the image build time, version, manufacturing package build time, image ID (or hash) etc. It is essentially a snapshot of the image data and metadata uploaded to the device flash at manufacturing time. Note that the command expects the targets and images to have already been built using newt build and newt create-image commands. deploy A combination of build and load commands to put together and upload manufacturing image on to the device. load Loads the manufacturing package onto to the flash of the connected device. Examples Suppose you have created two targets (one for the bootloader and one for the blinky app). $ newt target show targets/my_blinky_sim app=apps/blinky bsp=@apache-mynewt-core/hw/bsp/native build_profile=debug targets/rb_blinky app=apps/blinky bsp=@apache-mynewt-core/hw/bsp/rb-nano2 build_profile=debug targets/rb_boot app=@apache-mynewt-core/apps/boot bsp=@apache-mynewt-core/hw/bsp/rb-nano2 build_profile=optimized Create the directory to hold the mfg packages. $ mkdir -p mfgs/rb_blinky_rsa The rb_blinky_rsa package needs a pkg.yml file. In addition it is needs a mfg.yml file to specify the two constituent targets. An example of each file is shown below. $ more mfgs/rb_blinky_rsa/pkg.yml pkg.name: \"mfgs/rb_blinky_rsa\" pkg.type: \"mfg\" pkg.description: pkg.author: pkg.homepage: $ more mfgs/rb_blinky_rsa/mfg.yml mfg.bootloader: 'targets/rb_boot' mfg.images: - 'targets/rb_blinky' Build the bootloader and app images. $ newt build rb_boot $ newt create-image rb_blinky 0.0.1 Run the newt mfg create command to collect all the manufacturing snapshot files. $ newt mfg create rb_blinky_rsa Creating a manufacturing image from the following files: <snip> Generated the following files: <snip> $","title":"newt mfg"},{"location":"newt/command_list/newt_mfg/#newt-mfg","text":"Commands to create, build, and upload manufacturing image.","title":"newt mfg "},{"location":"newt/command_list/newt_mfg/#usage","text":"newt mfg [flags] newt mfg [command]","title":"Usage:"},{"location":"newt/command_list/newt_mfg/#available-commands","text":"create Create a manufacturing flash image deploy Build and upload a manufacturing image (build + load) load Load a manufacturing flash image onto a device","title":"Available Commands:"},{"location":"newt/command_list/newt_mfg/#global-flags","text":"-h, --help Help for newt commands -j, --jobs int Number of concurrent build jobs (default 8) -l, --loglevel string Log level (default \"WARN\") -o, --outfile string Filename to tee output to -q, --quiet Be quiet; only display error output -s, --silent Be silent; don't output anything -v, --verbose Enable verbose output when executing commands","title":"Global Flags:"},{"location":"newt/command_list/newt_mfg/#description","text":"Sub-command Explanation create A manufacturing image specifies 1) a boot loader target, and 2) one or more image targets. Assuming the manufacturing entity has been created and defined in the mfgs/<mfg image name>/ package (see Examples below), this command collects the manufacturing related files in the newly created bin/mfgs/<mfg image name> directory. The collection includes manifests with the image build time, version, manufacturing package build time, image ID (or hash) etc. It is essentially a snapshot of the image data and metadata uploaded to the device flash at manufacturing time. Note that the command expects the targets and images to have already been built using newt build and newt create-image commands. deploy A combination of build and load commands to put together and upload manufacturing image on to the device. load Loads the manufacturing package onto to the flash of the connected device.","title":"Description"},{"location":"newt/command_list/newt_mfg/#examples","text":"Suppose you have created two targets (one for the bootloader and one for the blinky app). $ newt target show targets/my_blinky_sim app=apps/blinky bsp=@apache-mynewt-core/hw/bsp/native build_profile=debug targets/rb_blinky app=apps/blinky bsp=@apache-mynewt-core/hw/bsp/rb-nano2 build_profile=debug targets/rb_boot app=@apache-mynewt-core/apps/boot bsp=@apache-mynewt-core/hw/bsp/rb-nano2 build_profile=optimized Create the directory to hold the mfg packages. $ mkdir -p mfgs/rb_blinky_rsa The rb_blinky_rsa package needs a pkg.yml file. In addition it is needs a mfg.yml file to specify the two constituent targets. An example of each file is shown below. $ more mfgs/rb_blinky_rsa/pkg.yml pkg.name: \"mfgs/rb_blinky_rsa\" pkg.type: \"mfg\" pkg.description: pkg.author: pkg.homepage: $ more mfgs/rb_blinky_rsa/mfg.yml mfg.bootloader: 'targets/rb_boot' mfg.images: - 'targets/rb_blinky' Build the bootloader and app images. $ newt build rb_boot $ newt create-image rb_blinky 0.0.1 Run the newt mfg create command to collect all the manufacturing snapshot files. $ newt mfg create rb_blinky_rsa Creating a manufacturing image from the following files: <snip> Generated the following files: <snip> $","title":"Examples"},{"location":"newt/command_list/newt_new/","text":"newt new Create a new project from a skeleton. Currently, the default skeleton is the blinky repository in Apache Mynewt (or https://github.com/apache/incubator-mynewt-blinky on its github mirror.) Usage: newt new <project-name> [flags] Global Flags: -h, --help Help for newt commands -j, --jobs int Number of concurrent build jobs (default 8) -l, --loglevel string Log level (default \"WARN\") -o, --outfile string Filename to tee output to -q, --quiet Be quiet; only display error output -s, --silent Be silent; don't output anything -v, --verbose Enable verbose output when executing commands Description Creates a new project named project-name from the default skeleton blinky repository in Apache Mynewt (or https://github.com/apache/incubator-mynewt-blinky on its github mirror.) Examples Sub-command Usage Explanation newt new test_project Creates a new project named test_project using the default skeleton from the apache/incubator-mynewt-blinky repository.","title":"newt new"},{"location":"newt/command_list/newt_new/#newt-new","text":"Create a new project from a skeleton. Currently, the default skeleton is the blinky repository in Apache Mynewt (or https://github.com/apache/incubator-mynewt-blinky on its github mirror.)","title":"newt new "},{"location":"newt/command_list/newt_new/#usage","text":"newt new <project-name> [flags]","title":"Usage:"},{"location":"newt/command_list/newt_new/#global-flags","text":"-h, --help Help for newt commands -j, --jobs int Number of concurrent build jobs (default 8) -l, --loglevel string Log level (default \"WARN\") -o, --outfile string Filename to tee output to -q, --quiet Be quiet; only display error output -s, --silent Be silent; don't output anything -v, --verbose Enable verbose output when executing commands","title":"Global Flags:"},{"location":"newt/command_list/newt_new/#description","text":"Creates a new project named project-name from the default skeleton blinky repository in Apache Mynewt (or https://github.com/apache/incubator-mynewt-blinky on its github mirror.)","title":"Description"},{"location":"newt/command_list/newt_new/#examples","text":"Sub-command Usage Explanation newt new test_project Creates a new project named test_project using the default skeleton from the apache/incubator-mynewt-blinky repository.","title":"Examples"},{"location":"newt/command_list/newt_pkg/","text":"newt pkg Commands for creating and manipulating packages. Usage: newt pkg [command] [flags] Flags: -t, --type string Type of package to create: pkg, bsp, sdk. (default \"pkg\") Global Flags: -h, --help Help for newt commands -j, --jobs int Number of concurrent build jobs (default 8) -l, --loglevel string Log level (default \"WARN\") -o, --outfile string Filename to tee output to -q, --quiet Be quiet; only display error output -s, --silent Be silent; don't output anything -v, --verbose Enable verbose output when executing commands Description The pkg command provides subcommands to create and manage packages. The subcommands take one or two package-name arguments. Sub-command Explanation copy The copy <src-pkg> <dst-pkg> command creates the new dst-pkg package by cloning the src-pkg package. move The move <old-pkg> <new-pkg> command moves the old-pkg package to the new-pkg package. new The new <new-pkg> command creates a new package named new-pkg , from a template, in the current directory. You can create a package of type pkg , bsp , or sdk . The default package type is pkg . You use the -t flag to specify a different package type. remove The remove <my-pkg> command deletes the my-pkg package. Examples Sub-command Usage Explanation copy newt pkg copy apps/bletiny apps/new_bletiny Copies the apps/bletiny package to the apps/new_bletiny . move newt pkg move apps/slinky apps/new_slinky Moves the apps/slinky package to the apps/new_slinky package. new newt pkg new apps/new_slinky Creates a package named apps/new_slinky of type pkg in the current directory. new newt pkg new hw/bsp/myboard -t bsp Creates a package named hw/bsp/myboard of type bsp in the current directory. remove newt pkg remove hw/bsp/myboard Removes the hw/bsp/myboard package.","title":"newt pkg"},{"location":"newt/command_list/newt_pkg/#newt-pkg","text":"Commands for creating and manipulating packages.","title":"newt pkg "},{"location":"newt/command_list/newt_pkg/#usage","text":"newt pkg [command] [flags]","title":"Usage:"},{"location":"newt/command_list/newt_pkg/#flags","text":"-t, --type string Type of package to create: pkg, bsp, sdk. (default \"pkg\")","title":"Flags:"},{"location":"newt/command_list/newt_pkg/#global-flags","text":"-h, --help Help for newt commands -j, --jobs int Number of concurrent build jobs (default 8) -l, --loglevel string Log level (default \"WARN\") -o, --outfile string Filename to tee output to -q, --quiet Be quiet; only display error output -s, --silent Be silent; don't output anything -v, --verbose Enable verbose output when executing commands","title":"Global Flags:"},{"location":"newt/command_list/newt_pkg/#description","text":"The pkg command provides subcommands to create and manage packages. The subcommands take one or two package-name arguments. Sub-command Explanation copy The copy <src-pkg> <dst-pkg> command creates the new dst-pkg package by cloning the src-pkg package. move The move <old-pkg> <new-pkg> command moves the old-pkg package to the new-pkg package. new The new <new-pkg> command creates a new package named new-pkg , from a template, in the current directory. You can create a package of type pkg , bsp , or sdk . The default package type is pkg . You use the -t flag to specify a different package type. remove The remove <my-pkg> command deletes the my-pkg package.","title":"Description"},{"location":"newt/command_list/newt_pkg/#examples","text":"Sub-command Usage Explanation copy newt pkg copy apps/bletiny apps/new_bletiny Copies the apps/bletiny package to the apps/new_bletiny . move newt pkg move apps/slinky apps/new_slinky Moves the apps/slinky package to the apps/new_slinky package. new newt pkg new apps/new_slinky Creates a package named apps/new_slinky of type pkg in the current directory. new newt pkg new hw/bsp/myboard -t bsp Creates a package named hw/bsp/myboard of type bsp in the current directory. remove newt pkg remove hw/bsp/myboard Removes the hw/bsp/myboard package.","title":"Examples"},{"location":"newt/command_list/newt_run/","text":"newt run A single command to do four steps - build a target, create-image, load image on a board, and start a debug session with the image on the board. Note : If the version number is omitted, the create-image step is skipped. Usage: newt run <target-name> [<version>][flags] Flags: --extrajtagcmd string Extra commands to send to JTAG software -n, --noGDB Do not start GDB from the command line Global Flags: -h, --help Help for newt commands -j, --jobs int Number of concurrent build jobs (default 8) -l, --loglevel string Log level (default \"WARN\") -o, --outfile string Filename to tee output to -q, --quiet Be quiet; only display error output -s, --silent Be silent; don't output anything -v, --verbose Enable verbose output when executing commands Description Same as running build <target-name> , create-image <target-name> <version> , load <target-name> , and debug <target-name> . Examples Sub-command Usage Explanation newt run blink_rigado Compiles and builds the image for the app and the bsp defined for target blink_rigado , loads the image onto the board, and opens an active GNU gdb debugging session to run the image. newt run ble_rigado 0.1.0.0 Compiles and builds the image for the app and the bsp defined for target ble_rigado , signs and creates the image with version number 0.1.0.0, loads the image onto the board, and opens an active GNU gdb debugging session to run the image. Note that if there is no bootloader available for a particular board/kit, a signed image creation step is not necessary.","title":"newt run"},{"location":"newt/command_list/newt_run/#newt-run","text":"A single command to do four steps - build a target, create-image, load image on a board, and start a debug session with the image on the board. Note : If the version number is omitted, the create-image step is skipped.","title":"newt run "},{"location":"newt/command_list/newt_run/#usage","text":"newt run <target-name> [<version>][flags]","title":"Usage:"},{"location":"newt/command_list/newt_run/#flags","text":"--extrajtagcmd string Extra commands to send to JTAG software -n, --noGDB Do not start GDB from the command line","title":"Flags:"},{"location":"newt/command_list/newt_run/#global-flags","text":"-h, --help Help for newt commands -j, --jobs int Number of concurrent build jobs (default 8) -l, --loglevel string Log level (default \"WARN\") -o, --outfile string Filename to tee output to -q, --quiet Be quiet; only display error output -s, --silent Be silent; don't output anything -v, --verbose Enable verbose output when executing commands","title":"Global Flags:"},{"location":"newt/command_list/newt_run/#description","text":"Same as running build <target-name> , create-image <target-name> <version> , load <target-name> , and debug <target-name> .","title":"Description"},{"location":"newt/command_list/newt_run/#examples","text":"Sub-command Usage Explanation newt run blink_rigado Compiles and builds the image for the app and the bsp defined for target blink_rigado , loads the image onto the board, and opens an active GNU gdb debugging session to run the image. newt run ble_rigado 0.1.0.0 Compiles and builds the image for the app and the bsp defined for target ble_rigado , signs and creates the image with version number 0.1.0.0, loads the image onto the board, and opens an active GNU gdb debugging session to run the image. Note that if there is no bootloader available for a particular board/kit, a signed image creation step is not necessary.","title":"Examples"},{"location":"newt/command_list/newt_size/","text":"newt size Calculates the size of target components for a target. Usage: newt size <target-name> [flags] Flags: -F, --flash Print FLASH statistics -R, --ram Print RAM statistics Global Flags: -h, --help Help for newt commands -j, --jobs int Number of concurrent build jobs (default 8) -l, --loglevel string Log level (default \"WARN\") -o, --outfile string Filename to tee output to -q, --quiet Be quiet; only display error output -s, --silent Be silent; don't output anything -v, --verbose Enable verbose output when executing commands Description Displays the RAM and FLASH size of each component for the target-name target. Examples Sub-command Usage Explanation newt size blink_rigado Inspects and lists the RAM and Flash memory that each component (object files and libraries) for the blink_rigado target. Example output for newt size blink_rigado : $ newt size blink_rigado FLASH RAM 9 223 *fill* 1052 0 baselibc.a 195 1116 blinky.a 616 452 bmd300eval.a 64 0 cmsis-core.a 124 0 crt0.o 8 0 crti.o 16 0 crtn.o 277 196 full.a 20 8 hal.a 96 1068 libg.a 1452 0 libgcc.a 332 28 nrf52xxx.a 3143 677 os.a objsize text data bss dec hex filename 7404 1172 2212 10788 2a24 /Users/<username>/dev/rigado/bin/blink_rigado/apps/blinky/blinky.elf","title":"newt size"},{"location":"newt/command_list/newt_size/#newt-size","text":"Calculates the size of target components for a target.","title":"newt size "},{"location":"newt/command_list/newt_size/#usage","text":"newt size <target-name> [flags]","title":"Usage:"},{"location":"newt/command_list/newt_size/#flags","text":"-F, --flash Print FLASH statistics -R, --ram Print RAM statistics","title":"Flags:"},{"location":"newt/command_list/newt_size/#global-flags","text":"-h, --help Help for newt commands -j, --jobs int Number of concurrent build jobs (default 8) -l, --loglevel string Log level (default \"WARN\") -o, --outfile string Filename to tee output to -q, --quiet Be quiet; only display error output -s, --silent Be silent; don't output anything -v, --verbose Enable verbose output when executing commands","title":"Global Flags:"},{"location":"newt/command_list/newt_size/#description","text":"Displays the RAM and FLASH size of each component for the target-name target.","title":"Description"},{"location":"newt/command_list/newt_size/#examples","text":"Sub-command Usage Explanation newt size blink_rigado Inspects and lists the RAM and Flash memory that each component (object files and libraries) for the blink_rigado target.","title":"Examples"},{"location":"newt/command_list/newt_size/#example-output-for-newt-size-blink_rigado","text":"$ newt size blink_rigado FLASH RAM 9 223 *fill* 1052 0 baselibc.a 195 1116 blinky.a 616 452 bmd300eval.a 64 0 cmsis-core.a 124 0 crt0.o 8 0 crti.o 16 0 crtn.o 277 196 full.a 20 8 hal.a 96 1068 libg.a 1452 0 libgcc.a 332 28 nrf52xxx.a 3143 677 os.a objsize text data bss dec hex filename 7404 1172 2212 10788 2a24 /Users/<username>/dev/rigado/bin/blink_rigado/apps/blinky/blinky.elf","title":"Example output for newt size blink_rigado:"},{"location":"newt/command_list/newt_sync/","text":"newt sync Synchronize and refresh the contents of the local copy of all the repositories used in the project with the latest updates maintained in the remote repositories. Usage: newt sync [flags] Flags: -f, --force Force overwrite of existing remote repository Global Flags: -h, --help Help for newt commands -j, --jobs int Number of concurrent build jobs (default 8) -l, --loglevel string Log level (default \"WARN\") -o, --outfile string Filename to tee output to -q, --quiet Be quiet; only display error output -s, --silent Be silent; don't output anything -v, --verbose Enable verbose output when executing commands Description Synchronize project dependencies and repositories. Prior to 1.0.0 release, the command deletes and resynchronizes each repository. Post 1.0.0, it will abort the synchronization if there are any local changes to any repository. Using the -f to force overwrite of existing repository will stash and save the changes while pulling in all the latest changes from the remote repository.","title":"newt sync"},{"location":"newt/command_list/newt_sync/#newt-sync","text":"Synchronize and refresh the contents of the local copy of all the repositories used in the project with the latest updates maintained in the remote repositories.","title":"newt sync "},{"location":"newt/command_list/newt_sync/#usage","text":"newt sync [flags]","title":"Usage:"},{"location":"newt/command_list/newt_sync/#flags","text":"-f, --force Force overwrite of existing remote repository","title":"Flags:"},{"location":"newt/command_list/newt_sync/#global-flags","text":"-h, --help Help for newt commands -j, --jobs int Number of concurrent build jobs (default 8) -l, --loglevel string Log level (default \"WARN\") -o, --outfile string Filename to tee output to -q, --quiet Be quiet; only display error output -s, --silent Be silent; don't output anything -v, --verbose Enable verbose output when executing commands","title":"Global Flags:"},{"location":"newt/command_list/newt_sync/#description","text":"Synchronize project dependencies and repositories. Prior to 1.0.0 release, the command deletes and resynchronizes each repository. Post 1.0.0, it will abort the synchronization if there are any local changes to any repository. Using the -f to force overwrite of existing repository will stash and save the changes while pulling in all the latest changes from the remote repository.","title":"Description"},{"location":"newt/command_list/newt_target/","text":"newt target Commands to create, delete, configure and query targets. Usage: newt target [command] [flags] Available Commands: config View or populate a target's system configuration settings copy Copy target create Create a target delete Delete target dep View target's dependency graph revdep View target's reverse-dependency graph set Set target configuration variable show View target configuration variables Global Flags: -h, --help Help for newt commands -j, --jobs int Number of concurrent build jobs (default 8) -l, --loglevel string Log level (default \"WARN\") -o, --outfile string Filename to tee output to -q, --quiet Be quiet; only display error output -s, --silent Be silent; don't output anything -v, --verbose Enable verbose output when executing commands Description The target command provides subcommands to create, build, delete, and query targets. The subcommands take one or two target-name arguments. Sub-command Explanation config The config command allows you to view or populate a target's system configuration settings. A target's system configuration settings include the settings of all the packages it includes. The settings for a package are listed in the package's syscfg.yml file. The config command has two subcommands: show and init . The config show <target-name> command displays the system configuration setting definitions and values for all the packages that the target-name target includes. The config init <target-name> command populates the target's syscfg.yml file with the system configuration values for all the packages that the target-name target includes. copy The copy <src-target> <dst-target> command creates a new target named dst-target by cloning the src-target target. create The create <target-name> command creates an empty target named target-name . It creates the targets/target-name directory and the skeleton pkg.yml and target.yml files in the directory. delete The delete <target-name> command deletes the description for the target-name target. It deletes the 'targets/target-name' directory. It does not delete the 'bin/targets/target-name' directory where the build artifacts are stored. If you want to delete the build artifacts, run the newt clean <target-name> command before deleting the target. dep The dep <target-name> command displays a dependency tree for the packages that the target-name target includes. It shows each package followed by the list of libraries or packages that it depends on. revdep The revdep <target-name> command displays the reverse dependency tree for the packages that the target-name target includes. It shows each package followed by the list of libraries or packages that depend on it. set The set <target-name> <var-name=var-value> [var-name=var-value...] command sets variables (attributes) for the <target-name> target. The set command overwrites your current variable values. The valid var-name values are: app , bsp , loader , build_profile , cflags , lflags , aflags , syscfg . The var-value format depends on the var-name as follows: app , bsp , loader : @<source-path>, where source-path is the directory containing the application or bsp source. These variables are stored in the target's target.yml file. For a simulated target, e.g. for software testing purposes, set bsp to @apache-mynewt-core/hw/bsp/native . build_profile : optimized or debug cflags , aflags , lflags : A string of flags, with each flag separated by a space. These variables are saved in the target's pkg.yml file. syscfg : The syscfg variable allows you to assign values to configuration settings in your target's syscfg.yml file. The format is syscfg=setting-name1=setting-value1[:setting-name2=setting-value2...] , where setting-name1 is a configuration setting name and setting-value1 is the value to assign to settingname1 . If settingvalue1 is not specified, the setting is set to value 1 . You use a : to delimit each setting when you set multiple settings. Warning : All existing setting values in the syscfg.yml file are deleted. Only new settings that are specified in the command are saved in the syscfg.yml file. You can specify var-name= or var-name=\"\" to unset a variable value. To display all the existing values for a target variable (attribute), you can run the newt vals <variable-name> command. For example, newt vals app displays the valid values available for the variable app for any target. show The show [target-name] command shows the values of the variables (attributes) for the target-name target. When target-name is not specified, the command shows the variables for all the targets that are defined for your project. Examples Sub-command Usage Explanation config show newt target config show rb_blinky Shows the system configuration settings for all the packages that the rb_blinky target includes. config init newt target config init my_blinky Creates and populates the my_blinky target's syscfg.yml file with the system configuration setting values from all the packages that the my_blinky target includes. copy newt target copy rb_blinky rb_bletiny Creates the rb_bletiny target by cloning the rb_blinky target. create newt target create my_new_target Creates the my_newt_target target. It creates the targets/my_new_target directory and creates the skeleton pkg.yml and target.yml files in the directory. delete newt target delete rb_bletiny Deletes the rb_bletiny target. It deletes the targets/rb_bletiny directory. dep newt target dep myble Displays the dependency tree of all the package dependencies for the myble target. It lists each package followed by a list of packages it depends on. revdep newt target revdep myble Displays the reverse dependency tree of all the package dependencies for the myble target. It lists each package followed by a list of packages that depend on it. set newt target set myble app=@apache-mynewt-core/apps/bletiny Use bletiny as the application to build for the myble target. set newt target set myble cflags=\"-DNDEBUG -Werror\" Set pkg.cflags variable with -DNDEBUG -Werror in the myble target's pkg.yml file.. set newt target set myble syscfg=LOG_NEWTMGR=0:CONFIG_NEWTMGR Sets the syscfg.vals variable in the myble target's syscfg.yml file with the setting values: LOG_NEWTMGR: 0 and CONFIG_NEWTMGR: 1. CONFIG_NEWTMGR is set to 1 because a value is not specified. set newt target set myble cflags= Unsets the pkg.cflags variable in the myble target's pkg.yml file. show newt target show myble Shows all variable settings for the myble target, i.e. the values that app, bsp, build_profile, cflags, aflags, ldflags, syscfg variables are set to. Note that not all variables have to be set for a target. show newt target show Shows all the variable settings for all the targets defined for the project.","title":"newt target"},{"location":"newt/command_list/newt_target/#newt-target","text":"Commands to create, delete, configure and query targets.","title":"newt target "},{"location":"newt/command_list/newt_target/#usage","text":"newt target [command] [flags]","title":"Usage:"},{"location":"newt/command_list/newt_target/#available-commands","text":"config View or populate a target's system configuration settings copy Copy target create Create a target delete Delete target dep View target's dependency graph revdep View target's reverse-dependency graph set Set target configuration variable show View target configuration variables","title":"Available Commands:"},{"location":"newt/command_list/newt_target/#global-flags","text":"-h, --help Help for newt commands -j, --jobs int Number of concurrent build jobs (default 8) -l, --loglevel string Log level (default \"WARN\") -o, --outfile string Filename to tee output to -q, --quiet Be quiet; only display error output -s, --silent Be silent; don't output anything -v, --verbose Enable verbose output when executing commands","title":"Global Flags:"},{"location":"newt/command_list/newt_target/#description","text":"The target command provides subcommands to create, build, delete, and query targets. The subcommands take one or two target-name arguments. Sub-command Explanation config The config command allows you to view or populate a target's system configuration settings. A target's system configuration settings include the settings of all the packages it includes. The settings for a package are listed in the package's syscfg.yml file. The config command has two subcommands: show and init . The config show <target-name> command displays the system configuration setting definitions and values for all the packages that the target-name target includes. The config init <target-name> command populates the target's syscfg.yml file with the system configuration values for all the packages that the target-name target includes. copy The copy <src-target> <dst-target> command creates a new target named dst-target by cloning the src-target target. create The create <target-name> command creates an empty target named target-name . It creates the targets/target-name directory and the skeleton pkg.yml and target.yml files in the directory. delete The delete <target-name> command deletes the description for the target-name target. It deletes the 'targets/target-name' directory. It does not delete the 'bin/targets/target-name' directory where the build artifacts are stored. If you want to delete the build artifacts, run the newt clean <target-name> command before deleting the target. dep The dep <target-name> command displays a dependency tree for the packages that the target-name target includes. It shows each package followed by the list of libraries or packages that it depends on. revdep The revdep <target-name> command displays the reverse dependency tree for the packages that the target-name target includes. It shows each package followed by the list of libraries or packages that depend on it. set The set <target-name> <var-name=var-value> [var-name=var-value...] command sets variables (attributes) for the <target-name> target. The set command overwrites your current variable values. The valid var-name values are: app , bsp , loader , build_profile , cflags , lflags , aflags , syscfg . The var-value format depends on the var-name as follows: app , bsp , loader : @<source-path>, where source-path is the directory containing the application or bsp source. These variables are stored in the target's target.yml file. For a simulated target, e.g. for software testing purposes, set bsp to @apache-mynewt-core/hw/bsp/native . build_profile : optimized or debug cflags , aflags , lflags : A string of flags, with each flag separated by a space. These variables are saved in the target's pkg.yml file. syscfg : The syscfg variable allows you to assign values to configuration settings in your target's syscfg.yml file. The format is syscfg=setting-name1=setting-value1[:setting-name2=setting-value2...] , where setting-name1 is a configuration setting name and setting-value1 is the value to assign to settingname1 . If settingvalue1 is not specified, the setting is set to value 1 . You use a : to delimit each setting when you set multiple settings. Warning : All existing setting values in the syscfg.yml file are deleted. Only new settings that are specified in the command are saved in the syscfg.yml file. You can specify var-name= or var-name=\"\" to unset a variable value. To display all the existing values for a target variable (attribute), you can run the newt vals <variable-name> command. For example, newt vals app displays the valid values available for the variable app for any target. show The show [target-name] command shows the values of the variables (attributes) for the target-name target. When target-name is not specified, the command shows the variables for all the targets that are defined for your project.","title":"Description"},{"location":"newt/command_list/newt_target/#examples","text":"Sub-command Usage Explanation config show newt target config show rb_blinky Shows the system configuration settings for all the packages that the rb_blinky target includes. config init newt target config init my_blinky Creates and populates the my_blinky target's syscfg.yml file with the system configuration setting values from all the packages that the my_blinky target includes. copy newt target copy rb_blinky rb_bletiny Creates the rb_bletiny target by cloning the rb_blinky target. create newt target create my_new_target Creates the my_newt_target target. It creates the targets/my_new_target directory and creates the skeleton pkg.yml and target.yml files in the directory. delete newt target delete rb_bletiny Deletes the rb_bletiny target. It deletes the targets/rb_bletiny directory. dep newt target dep myble Displays the dependency tree of all the package dependencies for the myble target. It lists each package followed by a list of packages it depends on. revdep newt target revdep myble Displays the reverse dependency tree of all the package dependencies for the myble target. It lists each package followed by a list of packages that depend on it. set newt target set myble app=@apache-mynewt-core/apps/bletiny Use bletiny as the application to build for the myble target. set newt target set myble cflags=\"-DNDEBUG -Werror\" Set pkg.cflags variable with -DNDEBUG -Werror in the myble target's pkg.yml file.. set newt target set myble syscfg=LOG_NEWTMGR=0:CONFIG_NEWTMGR Sets the syscfg.vals variable in the myble target's syscfg.yml file with the setting values: LOG_NEWTMGR: 0 and CONFIG_NEWTMGR: 1. CONFIG_NEWTMGR is set to 1 because a value is not specified. set newt target set myble cflags= Unsets the pkg.cflags variable in the myble target's pkg.yml file. show newt target show myble Shows all variable settings for the myble target, i.e. the values that app, bsp, build_profile, cflags, aflags, ldflags, syscfg variables are set to. Note that not all variables have to be set for a target. show newt target show Shows all the variable settings for all the targets defined for the project.","title":"Examples"},{"location":"newt/command_list/newt_test/","text":"newt test Execute unit tests for one or more packages. Usage: newt test <package-name> [package-names...] | all [flags] Flags: -e, --exclude string Comma separated list of packages to exclude Global Flags: -h, --help Help for newt commands -j, --jobs int Number of concurrent build jobs (default 8) -l, --loglevel string Log level (default \"WARN\") -o, --outfile string Filename to tee output to -q, --quiet Be quiet; only display error output -s, --silent Be silent; don't output anything -v, --verbose Enable verbose output when executing commands Description Executes unit tests for one or more packages. You specify a list of packages, separated by space, to test multiple packages in the same command, or specify all to test all packages. When you use the all option, you may use the -e flag followed by a comma separated list of packages to exclude from the test. Examples Sub-command Usage Explanation newt test @apache-mynewt-core/kernel/os Tests the kernel/os package in the apache-mynewt-core repository. newt test kernel/os encoding/json Tests the kernel/os and encoding/json packages in the current repository. newt test all Tests all packages. newt test all -e net/oic,encoding/json Tests all packages except for the net/oic and the encoding/json packages.","title":"newt test"},{"location":"newt/command_list/newt_test/#newt-test","text":"Execute unit tests for one or more packages.","title":"newt test "},{"location":"newt/command_list/newt_test/#usage","text":"newt test <package-name> [package-names...] | all [flags]","title":"Usage:"},{"location":"newt/command_list/newt_test/#flags","text":"-e, --exclude string Comma separated list of packages to exclude","title":"Flags:"},{"location":"newt/command_list/newt_test/#global-flags","text":"-h, --help Help for newt commands -j, --jobs int Number of concurrent build jobs (default 8) -l, --loglevel string Log level (default \"WARN\") -o, --outfile string Filename to tee output to -q, --quiet Be quiet; only display error output -s, --silent Be silent; don't output anything -v, --verbose Enable verbose output when executing commands","title":"Global Flags:"},{"location":"newt/command_list/newt_test/#description","text":"Executes unit tests for one or more packages. You specify a list of packages, separated by space, to test multiple packages in the same command, or specify all to test all packages. When you use the all option, you may use the -e flag followed by a comma separated list of packages to exclude from the test.","title":"Description"},{"location":"newt/command_list/newt_test/#examples","text":"Sub-command Usage Explanation newt test @apache-mynewt-core/kernel/os Tests the kernel/os package in the apache-mynewt-core repository. newt test kernel/os encoding/json Tests the kernel/os and encoding/json packages in the current repository. newt test all Tests all packages. newt test all -e net/oic,encoding/json Tests all packages except for the net/oic and the encoding/json packages.","title":"Examples"},{"location":"newt/command_list/newt_upgrade/","text":"newt upgrade Upgrade project dependencies. Usage: newt upgrade [flags] Flags: -f, --force Force upgrade of the repositories to latest state in project.yml Global Flags: -h, --help Help for newt commands -j, --jobs int Number of concurrent build jobs (default 8) -l, --loglevel string Log level (default \"WARN\") -o, --outfile string Filename to tee output to -q, --quiet Be quiet; only display error output -s, --silent Be silent; don't output anything -v, --verbose Enable verbose output when executing commands Description Upagrades your project and package dependencies. If you have changed the project.yml description for the project, you need to run this command to update all the package dependencies.","title":"newt upgrade"},{"location":"newt/command_list/newt_upgrade/#newt-upgrade","text":"Upgrade project dependencies.","title":"newt upgrade "},{"location":"newt/command_list/newt_upgrade/#usage","text":"newt upgrade [flags]","title":"Usage:"},{"location":"newt/command_list/newt_upgrade/#flags","text":"-f, --force Force upgrade of the repositories to latest state in project.yml","title":"Flags:"},{"location":"newt/command_list/newt_upgrade/#global-flags","text":"-h, --help Help for newt commands -j, --jobs int Number of concurrent build jobs (default 8) -l, --loglevel string Log level (default \"WARN\") -o, --outfile string Filename to tee output to -q, --quiet Be quiet; only display error output -s, --silent Be silent; don't output anything -v, --verbose Enable verbose output when executing commands","title":"Global Flags:"},{"location":"newt/command_list/newt_upgrade/#description","text":"Upagrades your project and package dependencies. If you have changed the project.yml description for the project, you need to run this command to update all the package dependencies.","title":"Description"},{"location":"newt/command_list/newt_vals/","text":"newt vals Display valid values for the specified element type(s). Usage: newt vals <element-type> [element-types...] [flags] Global Flags: -h, --help Help for newt commands -j, --jobs int Number of concurrent build jobs (default 8) -l, --loglevel string Log level (default \"WARN\") -o, --outfile string Filename to tee output to -q, --quiet Be quiet; only display error output -s, --silent Be silent; don't output anything -v, --verbose Enable verbose output when executing commands Description Displays valid values for the specified element type(s). You must set valid values for one or more elements when you define a package or a target. Valid element types are: api app bsp build_profile compiler lib sdk target Examples Sub-command Usage Explanation newt vals api Shows the possible values for APIs a package may specify as required. For example, the pkg.yml for adc specifies that it requires the api named ADC_HW_IMPL , one of the values listed by the command. Example output for newt vals bsp : This lists all possible values that may be assigned to a target's bsp attribute. $ newt vals bsp bsp names: @apache-mynewt-core/hw/bsp/arduino_primo_nrf52 @apache-mynewt-core/hw/bsp/bmd300eval @apache-mynewt-core/hw/bsp/ci40 @apache-mynewt-core/hw/bsp/frdm-k64f @apache-mynewt-core/hw/bsp/native @apache-mynewt-core/hw/bsp/nrf51-arduino_101 @apache-mynewt-core/hw/bsp/nrf51-blenano @apache-mynewt-core/hw/bsp/nrf51dk @apache-mynewt-core/hw/bsp/nrf51dk-16kbram @apache-mynewt-core/hw/bsp/nrf52dk @apache-mynewt-core/hw/bsp/nucleo-f401re @apache-mynewt-core/hw/bsp/olimex_stm32-e407_devboard @apache-mynewt-core/hw/bsp/rb-nano2 @apache-mynewt-core/hw/bsp/stm32f4discovery $ newt target set sample_target bsp=@apache-mynewt-core/hw/bsp/rb-nano2 Obviously, this output will grow as more board support packages are added for new boards and MCUs.","title":"newt vals"},{"location":"newt/command_list/newt_vals/#newt-vals","text":"Display valid values for the specified element type(s).","title":"newt vals "},{"location":"newt/command_list/newt_vals/#usage","text":"newt vals <element-type> [element-types...] [flags]","title":"Usage:"},{"location":"newt/command_list/newt_vals/#global-flags","text":"-h, --help Help for newt commands -j, --jobs int Number of concurrent build jobs (default 8) -l, --loglevel string Log level (default \"WARN\") -o, --outfile string Filename to tee output to -q, --quiet Be quiet; only display error output -s, --silent Be silent; don't output anything -v, --verbose Enable verbose output when executing commands","title":"Global Flags:"},{"location":"newt/command_list/newt_vals/#description","text":"Displays valid values for the specified element type(s). You must set valid values for one or more elements when you define a package or a target. Valid element types are: api app bsp build_profile compiler lib sdk target","title":"Description"},{"location":"newt/command_list/newt_vals/#examples","text":"Sub-command Usage Explanation newt vals api Shows the possible values for APIs a package may specify as required. For example, the pkg.yml for adc specifies that it requires the api named ADC_HW_IMPL , one of the values listed by the command.","title":"Examples"},{"location":"newt/command_list/newt_vals/#example-output-for-newt-vals-bsp","text":"This lists all possible values that may be assigned to a target's bsp attribute. $ newt vals bsp bsp names: @apache-mynewt-core/hw/bsp/arduino_primo_nrf52 @apache-mynewt-core/hw/bsp/bmd300eval @apache-mynewt-core/hw/bsp/ci40 @apache-mynewt-core/hw/bsp/frdm-k64f @apache-mynewt-core/hw/bsp/native @apache-mynewt-core/hw/bsp/nrf51-arduino_101 @apache-mynewt-core/hw/bsp/nrf51-blenano @apache-mynewt-core/hw/bsp/nrf51dk @apache-mynewt-core/hw/bsp/nrf51dk-16kbram @apache-mynewt-core/hw/bsp/nrf52dk @apache-mynewt-core/hw/bsp/nucleo-f401re @apache-mynewt-core/hw/bsp/olimex_stm32-e407_devboard @apache-mynewt-core/hw/bsp/rb-nano2 @apache-mynewt-core/hw/bsp/stm32f4discovery $ newt target set sample_target bsp=@apache-mynewt-core/hw/bsp/rb-nano2 Obviously, this output will grow as more board support packages are added for new boards and MCUs.","title":"Example output for newt vals bsp:"},{"location":"newt/command_list/newt_version/","text":"newt version Display the version of the newt tool you have installed Usage: newt version [flags] Global Flags: -h, --help Help for newt commands -j, --jobs int Number of concurrent build jobs (default 8) -l, --loglevel string Log level (default \"WARN\") -o, --outfile string Filename to tee output to -q, --quiet Be quiet; only display error output -s, --silent Be silent; don't output anything -v, --verbose Enable verbose output when executing commands Examples Sub-command Usage Explanation newt version Displays the version of the newt tool you have installed","title":"newt version"},{"location":"newt/command_list/newt_version/#newt-version","text":"Display the version of the newt tool you have installed","title":"newt version "},{"location":"newt/command_list/newt_version/#usage","text":"newt version [flags]","title":"Usage:"},{"location":"newt/command_list/newt_version/#global-flags","text":"-h, --help Help for newt commands -j, --jobs int Number of concurrent build jobs (default 8) -l, --loglevel string Log level (default \"WARN\") -o, --outfile string Filename to tee output to -q, --quiet Be quiet; only display error output -s, --silent Be silent; don't output anything -v, --verbose Enable verbose output when executing commands","title":"Global Flags:"},{"location":"newt/command_list/newt_version/#examples","text":"Sub-command Usage Explanation newt version Displays the version of the newt tool you have installed","title":"Examples"},{"location":"newt/install/newt_linux/","text":"Installing Newt on Linux You can install the latest stable release (1.0.0) of the newt tool from a Debian binary package (amd64) or from a Debian source package. This page shows you how to: Set up your computer to retrieve Debian packages from the runtimeco debian package repository. Install the latest stable release version of newt from a Debian binary package. Install the latest stable release version of newt from a Debian source package. If you are installing on an amd64 platform, we recommend that you install from the binary package. Note: We have tested the newt tool binary and apt-get install from the runtimeco Debian package repository for Ubuntu version 16. Earlier Ubuntu versions (for example: Ubuntu 14) may have incompatibility with the repository. We recommend that you upgrade Ubuntu on your computer. Note: See Setting Up an Go Environment to Contribute to Newt and Newtmgr Tools if you want to: Use the newt tool with the latest updates from the master branch. The master branch may be unstable and we recommend that you use the latest stable release version. Contribute to the newt tool. Setting Up Your Computer to Get Packages from runtimeco The newt Debian packages are stored in a private repository on https://github/runtimeco/debian-mynewt . The following steps must be performed on your computer to retreive packages from the repository: Note: You only need to perform this setup once on your computer. Install the apt-transport-https package to use HTTPS to retrieve packages. Download the public key for the runtimeco debian repository and import the key into the apt keychain. Add the repository for the binary and source packages to the apt source list. Install the apt-transport-https package: $sudo apt-get update $sudo apt-get install apt-transport-https Download the public key for the runtimeco apt repo ( Note: There is a - after apt-key add ): wget -qO - https://raw.githubusercontent.com/runtimeco/debian-mynewt/master/mynewt.gpg.key | sudo apt-key add - Add the repository for the binary and source packages to the mynewt.list apt source list file. $sudo -s [sudo] password for <user>: root$ cat > /etc/apt/sources.list.d/mynewt.list <<EOF deb https://raw.githubusercontent.com/runtimeco/debian-mynewt/master latest main deb-src https://raw.githubusercontent.com/runtimeco/debian-mynewt/master latest main EOF root$exit Note: Do not forget to exit the root shell. Verify the content of the source list file: $more /etc/apt/sources.list.d/mynewt.list deb https://raw.githubusercontent.com/runtimeco/debian-mynewt/master latest main deb-src https://raw.githubusercontent.com/runtimeco/debian-mynewt/master latest main Update the available packages: $sudo apt-get update Note: If you are not using Ubuntu version 16, you may see the following errors. We recommend that you upgrade Ubuntu. We have provided instructions on how to manually download and install the binary package if you choose not to upgrade, but you will want to upgrade Ubuntu if you are installing from source. W: Failed to fetch https://raw.githubusercontent.com/runtimeco/debian-mynewt/master/dists/latest/main/source/Sources HttpError404 W: Failed to fetch https://raw.githubusercontent.com/runtimeco/debian-mynewt/master/dists/latest/main/binary-amd64/Packages Bad header line W: Failed to fetch https://raw.githubusercontent.com/runtimeco/debian-mynewt/master/dists/latest/main/binary-i386/Packages HttpError404 E: Some index files failed to download. They have been ignored, or old ones used instead. Installing the Latest Release of Newt from a Binary Package For Linux amd64 platforms, you can install the latest stable version (1.0.0) of newt from the newt Debian binary package. $sudo apt-get install newt Reading package lists... Done Building dependency tree Reading state information... Done ... Preparing to unpack .../newt_1.0.0-1_amd64.deb ... Unpacking newt (1.0.0-1) ... Setting up newt (1.0.0-1) ... Note: If you are not using Ubuntu version 16 and are not able to update the runtimeco Debian package repo on your computer successfully, you can manually download and install the newt_1.0.0-1_amd64.deb binary package as follows: $wget https://raw.githubusercontent.com/runtimeco/debian-mynewt/master/pool/main/n/newt/newt_1.0.0-1_amd64.deb $sudo dpkg -i newt_1.0.0-1_amd64.deb See Checking the Installed Version of Newt to verify that you are using the installed version of newt. Installing the Latest Stable Release of Newt from a Source Package If you are running Linux on a different architecture, you can install the Debian source package for the latest stable release (1.0.0) of newt. The installation of the source package builds the newt binary and creates a Debian binary package that you then install. Note : Newt version 1.0.0 has been tested on Linux amd64 platforms. Version 1.0.0 does not build on 32 bit platforms but have been fixed for the next release. Installing Go 1.7 You need Go version 1.7 or higher to build Newt version 1.0.0. Currently, the latest Go version that Ubuntu installs is 1.6. Run go version to check if you have Go 1.7 installed. Install Go version 1.7: $sudo apt-get install golang-1.7-go Reading package lists... Done ... Unpacking golang-1.7-go (1.7.1-2ubuntu1) ... Setting up golang-1.7-go (1.7.1-2ubuntu1) ... $ $sudo ln -sf ../lib/go-1.7/bin/go /usr/bin/go $go version go version go1.7.1 linux/amd64 You can also download version 1.7 from https://golang.org/dl/ . Installing from the Source Package Create a directory and change into the directory, download the source package, and build a binary package from the source package: mkdir newt_source $cd newt_source $sudo apt-get --build source newt [sudo] password for <user>: Reading package lists... Done Need to get 1,866 kB of source archives. Get:1 https://raw.githubusercontent.com/runtimeco/debian-mynewt/master latest/main newt 1.0.0-1 (dsc) [795 B] Get:2 https://raw.githubusercontent.com/runtimeco/debian-mynewt/master latest/main newt 1.0.0-1 (tar) [1,864 kB] Get:3 https://raw.githubusercontent.com/runtimeco/debian-mynewt/master latest/main newt 1.0.0-1 (diff) [2,000 B] Fetched 1,866 kB in 1s (1,222 kB/s) dpkg-source: warning: extracting unsigned source package (newt_1.0.0-1.dsc) dpkg-source: info: extracting newt in newt-1.0.0 dpkg-source: info: unpacking newt_1.0.0.orig.tar.gz dpkg-source: info: unpacking newt_1.0.0-1.debian.tar.xz ... dpkg-deb: building package 'newt' in '../newt_1.0.0-1_amd64.deb'. dpkg-genchanges --build=any,all >../newt_1.0.0-1_amd64.changes dpkg-genchanges: info: binary-only upload (no source code included) dpkg-source --after-build newt-1.0.0 dpkg-buildpackage: info: binary-only upload (no source included) W: Can't drop privileges for downloading as file 'newt_1.0.0-1.dsc' couldn't be accessed by user '_apt'. - pkgAcquire::Run (13: Permission denied) Note: You can ignore the \"Permission denied\" warning message at the end of the command. Install the newt binary package that is created from the source package: Note: The file name for the binary package has the format: newt_1.0.0-1_ arch .deb, where arch is a value that identifies your host architecture. $sudo dpkg -i newt_1.0.0-1_amd64.deb Selecting previously unselected package newt. (Reading database ... 252969 files and directories currently installed.) Preparing to unpack newt_1.0.0-1_amd64.deb ... Unpacking newt (1.0.0-1) ... Setting up newt (1.0.0-1) ... Checking the Installed Version of Newt After you have installed newt from either a Debian binary or source package, check that you are using the installed version of newt from /usr/bin . Check the modification time of the binary and the newt tool that you are using: $ls -l /usr/bin/newt -rwxr-xr-x 1 root root 6919280 Apr 22 10:09 /usr/bin/newt $which newt /usr/bin/newt $newt version Apache Newt (incubating) version: 1.0.0 Note: If you previously built newt from source and the output of which newt shows \"$GOPATH/bin/newt\", you will need to move \"$GOPATH/bin\" after \"/usr/bin\" for your PATH environment variable and export it. Get information about newt: $newt Newt allows you to create your own embedded application based on the Mynewt operating system. Newt provides both build and package management in a single tool, which allows you to compose an embedded application, and set of projects, and then build the necessary artifacts from those projects. For more information on the Mynewt operating system, please visit https://mynewt.apache.org/. Please use the newt help command, and specify the name of the command you want help for, for help on how to use a specific command Usage: newt [flags] newt [command] Examples: newt newt help [<command-name>] For help on <command-name>. If not specified, print this message. Available Commands: build Build one or more targets clean Delete build artifacts for one or more targets create-image Add image header to target binary debug Open debugger session to target info Show project info install Install project dependencies load Load built target to board mfg Manufacturing flash image commands new Create a new project pkg Create and manage packages in the current workspace run build/create-image/download/debug <target> size Size of target components sync Synchronize project dependencies target Commands to create, delete, configure, and query targets test Executes unit tests for one or more packages upgrade Upgrade project dependencies vals Display valid values for the specified element type(s) version Display the Newt version number Flags: -h, --help Help for newt commands -j, --jobs int Number of concurrent build jobs (default 8) -l, --loglevel string Log level (default \"WARN\") -o, --outfile string Filename to tee output to -q, --quiet Be quiet; only display error output -s, --silent Be silent; don't output anything -v, --verbose Enable verbose output when executing commands Use \"newt [command] --help\" for more information about a command.","title":"Install Newt on Linux"},{"location":"newt/install/newt_linux/#installing-newt-on-linux","text":"You can install the latest stable release (1.0.0) of the newt tool from a Debian binary package (amd64) or from a Debian source package. This page shows you how to: Set up your computer to retrieve Debian packages from the runtimeco debian package repository. Install the latest stable release version of newt from a Debian binary package. Install the latest stable release version of newt from a Debian source package. If you are installing on an amd64 platform, we recommend that you install from the binary package. Note: We have tested the newt tool binary and apt-get install from the runtimeco Debian package repository for Ubuntu version 16. Earlier Ubuntu versions (for example: Ubuntu 14) may have incompatibility with the repository. We recommend that you upgrade Ubuntu on your computer. Note: See Setting Up an Go Environment to Contribute to Newt and Newtmgr Tools if you want to: Use the newt tool with the latest updates from the master branch. The master branch may be unstable and we recommend that you use the latest stable release version. Contribute to the newt tool.","title":"Installing Newt on Linux"},{"location":"newt/install/newt_linux/#setting-up-your-computer-to-get-packages-from-runtimeco","text":"The newt Debian packages are stored in a private repository on https://github/runtimeco/debian-mynewt . The following steps must be performed on your computer to retreive packages from the repository: Note: You only need to perform this setup once on your computer. Install the apt-transport-https package to use HTTPS to retrieve packages. Download the public key for the runtimeco debian repository and import the key into the apt keychain. Add the repository for the binary and source packages to the apt source list. Install the apt-transport-https package: $sudo apt-get update $sudo apt-get install apt-transport-https Download the public key for the runtimeco apt repo ( Note: There is a - after apt-key add ): wget -qO - https://raw.githubusercontent.com/runtimeco/debian-mynewt/master/mynewt.gpg.key | sudo apt-key add - Add the repository for the binary and source packages to the mynewt.list apt source list file. $sudo -s [sudo] password for <user>: root$ cat > /etc/apt/sources.list.d/mynewt.list <<EOF deb https://raw.githubusercontent.com/runtimeco/debian-mynewt/master latest main deb-src https://raw.githubusercontent.com/runtimeco/debian-mynewt/master latest main EOF root$exit Note: Do not forget to exit the root shell. Verify the content of the source list file: $more /etc/apt/sources.list.d/mynewt.list deb https://raw.githubusercontent.com/runtimeco/debian-mynewt/master latest main deb-src https://raw.githubusercontent.com/runtimeco/debian-mynewt/master latest main Update the available packages: $sudo apt-get update Note: If you are not using Ubuntu version 16, you may see the following errors. We recommend that you upgrade Ubuntu. We have provided instructions on how to manually download and install the binary package if you choose not to upgrade, but you will want to upgrade Ubuntu if you are installing from source. W: Failed to fetch https://raw.githubusercontent.com/runtimeco/debian-mynewt/master/dists/latest/main/source/Sources HttpError404 W: Failed to fetch https://raw.githubusercontent.com/runtimeco/debian-mynewt/master/dists/latest/main/binary-amd64/Packages Bad header line W: Failed to fetch https://raw.githubusercontent.com/runtimeco/debian-mynewt/master/dists/latest/main/binary-i386/Packages HttpError404 E: Some index files failed to download. They have been ignored, or old ones used instead.","title":"Setting Up Your Computer to Get Packages from runtimeco"},{"location":"newt/install/newt_linux/#installing-the-latest-release-of-newt-from-a-binary-package","text":"For Linux amd64 platforms, you can install the latest stable version (1.0.0) of newt from the newt Debian binary package. $sudo apt-get install newt Reading package lists... Done Building dependency tree Reading state information... Done ... Preparing to unpack .../newt_1.0.0-1_amd64.deb ... Unpacking newt (1.0.0-1) ... Setting up newt (1.0.0-1) ... Note: If you are not using Ubuntu version 16 and are not able to update the runtimeco Debian package repo on your computer successfully, you can manually download and install the newt_1.0.0-1_amd64.deb binary package as follows: $wget https://raw.githubusercontent.com/runtimeco/debian-mynewt/master/pool/main/n/newt/newt_1.0.0-1_amd64.deb $sudo dpkg -i newt_1.0.0-1_amd64.deb See Checking the Installed Version of Newt to verify that you are using the installed version of newt.","title":"Installing the Latest Release of Newt from a Binary Package"},{"location":"newt/install/newt_linux/#installing-the-latest-stable-release-of-newt-from-a-source-package","text":"If you are running Linux on a different architecture, you can install the Debian source package for the latest stable release (1.0.0) of newt. The installation of the source package builds the newt binary and creates a Debian binary package that you then install. Note : Newt version 1.0.0 has been tested on Linux amd64 platforms. Version 1.0.0 does not build on 32 bit platforms but have been fixed for the next release.","title":"Installing the Latest Stable Release of Newt from a Source Package"},{"location":"newt/install/newt_linux/#installing-go-17","text":"You need Go version 1.7 or higher to build Newt version 1.0.0. Currently, the latest Go version that Ubuntu installs is 1.6. Run go version to check if you have Go 1.7 installed. Install Go version 1.7: $sudo apt-get install golang-1.7-go Reading package lists... Done ... Unpacking golang-1.7-go (1.7.1-2ubuntu1) ... Setting up golang-1.7-go (1.7.1-2ubuntu1) ... $ $sudo ln -sf ../lib/go-1.7/bin/go /usr/bin/go $go version go version go1.7.1 linux/amd64 You can also download version 1.7 from https://golang.org/dl/ .","title":"Installing Go 1.7"},{"location":"newt/install/newt_linux/#installing-from-the-source-package","text":"Create a directory and change into the directory, download the source package, and build a binary package from the source package: mkdir newt_source $cd newt_source $sudo apt-get --build source newt [sudo] password for <user>: Reading package lists... Done Need to get 1,866 kB of source archives. Get:1 https://raw.githubusercontent.com/runtimeco/debian-mynewt/master latest/main newt 1.0.0-1 (dsc) [795 B] Get:2 https://raw.githubusercontent.com/runtimeco/debian-mynewt/master latest/main newt 1.0.0-1 (tar) [1,864 kB] Get:3 https://raw.githubusercontent.com/runtimeco/debian-mynewt/master latest/main newt 1.0.0-1 (diff) [2,000 B] Fetched 1,866 kB in 1s (1,222 kB/s) dpkg-source: warning: extracting unsigned source package (newt_1.0.0-1.dsc) dpkg-source: info: extracting newt in newt-1.0.0 dpkg-source: info: unpacking newt_1.0.0.orig.tar.gz dpkg-source: info: unpacking newt_1.0.0-1.debian.tar.xz ... dpkg-deb: building package 'newt' in '../newt_1.0.0-1_amd64.deb'. dpkg-genchanges --build=any,all >../newt_1.0.0-1_amd64.changes dpkg-genchanges: info: binary-only upload (no source code included) dpkg-source --after-build newt-1.0.0 dpkg-buildpackage: info: binary-only upload (no source included) W: Can't drop privileges for downloading as file 'newt_1.0.0-1.dsc' couldn't be accessed by user '_apt'. - pkgAcquire::Run (13: Permission denied) Note: You can ignore the \"Permission denied\" warning message at the end of the command. Install the newt binary package that is created from the source package: Note: The file name for the binary package has the format: newt_1.0.0-1_ arch .deb, where arch is a value that identifies your host architecture. $sudo dpkg -i newt_1.0.0-1_amd64.deb Selecting previously unselected package newt. (Reading database ... 252969 files and directories currently installed.) Preparing to unpack newt_1.0.0-1_amd64.deb ... Unpacking newt (1.0.0-1) ... Setting up newt (1.0.0-1) ...","title":"Installing from the Source Package"},{"location":"newt/install/newt_linux/#checking-the-installed-version-of-newt","text":"After you have installed newt from either a Debian binary or source package, check that you are using the installed version of newt from /usr/bin . Check the modification time of the binary and the newt tool that you are using: $ls -l /usr/bin/newt -rwxr-xr-x 1 root root 6919280 Apr 22 10:09 /usr/bin/newt $which newt /usr/bin/newt $newt version Apache Newt (incubating) version: 1.0.0 Note: If you previously built newt from source and the output of which newt shows \"$GOPATH/bin/newt\", you will need to move \"$GOPATH/bin\" after \"/usr/bin\" for your PATH environment variable and export it. Get information about newt: $newt Newt allows you to create your own embedded application based on the Mynewt operating system. Newt provides both build and package management in a single tool, which allows you to compose an embedded application, and set of projects, and then build the necessary artifacts from those projects. For more information on the Mynewt operating system, please visit https://mynewt.apache.org/. Please use the newt help command, and specify the name of the command you want help for, for help on how to use a specific command Usage: newt [flags] newt [command] Examples: newt newt help [<command-name>] For help on <command-name>. If not specified, print this message. Available Commands: build Build one or more targets clean Delete build artifacts for one or more targets create-image Add image header to target binary debug Open debugger session to target info Show project info install Install project dependencies load Load built target to board mfg Manufacturing flash image commands new Create a new project pkg Create and manage packages in the current workspace run build/create-image/download/debug <target> size Size of target components sync Synchronize project dependencies target Commands to create, delete, configure, and query targets test Executes unit tests for one or more packages upgrade Upgrade project dependencies vals Display valid values for the specified element type(s) version Display the Newt version number Flags: -h, --help Help for newt commands -j, --jobs int Number of concurrent build jobs (default 8) -l, --loglevel string Log level (default \"WARN\") -o, --outfile string Filename to tee output to -q, --quiet Be quiet; only display error output -s, --silent Be silent; don't output anything -v, --verbose Enable verbose output when executing commands Use \"newt [command] --help\" for more information about a command.","title":" Checking the Installed Version of Newt"},{"location":"newt/install/newt_mac/","text":"Installing Newt on Mac OS Newt is supported on Mac OS X 64 bit platforms and has been tested on Mac OS 10.9 and higher. This page shows you how to install the following versions of newt: The latest stable release version (1.0.0) The latest from the master branch (unstable) Note: If you would like to contribute to the newt tool, see Setting Up Go Environment to Contribute to Newt and Newtmgr Tools . Installing Homebrew If you do not have Homebrew installed, run the following command. You will be prompted for your sudo password. $ ruby -e \"$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)\" You can also extract (or git clone ) Homebrew and install it to /usr/local. Installing Newt Add the ** runtimeco/homebrew-mynewt ** tap: $brew tap runtimeco/homebrew-mynewt $brew update Installing the Latest Release Version of Newt Install the latest stable release version (1.0.0) of newt: $brew install mynewt-newt ==> Installing mynewt-newt from runtimeco/mynewt ==> Downloading https://github.com/runtimeco/binary-releases/raw/master/mynewt-newt-tools_1.0.0/mynewt-newt-1.0.0.mavericks.bottle.tar.gz ==> Downloading from https://raw.githubusercontent.com/runtimeco/binary-releases/master/mynewt-newt-tools_1.0.0/mynewt-newt-1.0.0.mavericks. ######################################################################## 100.0% ==> Pouring mynewt-newt-1.0.0.mavericks.bottle.tar.gz \ud83c\udf7a /usr/local/Cellar/mynewt-newt/1.0.0: 3 files, 10.4MB Note: This installs the newt 1.0.0 binary that has been tested on Mac OS 10.9 and higher. If you are running an earlier version of Mac OS, the installation will install the latest version of Go and compile newt locally. Check that you are using the installed version of newt: $which newt /usr/local/bin/newt $ls -l /usr/local/bin/newt lrwxr-xr-x 1 user staff 36 Apr 15 08:18 /usr/local/bin/newt -> ../Cellar/mynewt-newt/1.0.0/bin/newt $newt version Apache Newt (incubating) version: 1.0.0 Note: If you previously built newt from source and the output of which newt shows \"$GOPATH/bin/newt\", you will need to move \"$GOPATH/bin\" after \"/usr/local/bin\" in your $PATH. Get information about newt: $newt help Newt allows you to create your own embedded application based on the Mynewt operating system. Newt provides both build and package management in a single tool, which allows you to compose an embedded application, and set of projects, and then build the necessary artifacts from those projects. For more information on the Mynewt operating system, please visit https://mynewt.apache.org/. Please use the newt help command, and specify the name of the command you want help for, for help on how to use a specific command Usage: newt [flags] newt [command] Examples: newt newt help [<command-name>] For help on <command-name>. If not specified, print this message. Available Commands: build Build one or more targets clean Delete build artifacts for one or more targets create-image Add image header to target binary debug Open debugger session to target info Show project info install Install project dependencies load Load built target to board mfg Manufacturing flash image commands new Create a new project pkg Create and manage packages in the current workspace run build/create-image/download/debug <target> size Size of target components sync Synchronize project dependencies target Commands to create, delete, configure, and query targets test Executes unit tests for one or more packages upgrade Upgrade project dependencies vals Display valid values for the specified element type(s) version Display the Newt version number Flags: -h, --help Help for newt commands -j, --jobs int Number of concurrent build jobs (default 8) -l, --loglevel string Log level (default \"WARN\") -o, --outfile string Filename to tee output to -q, --quiet Be quiet; only display error output -s, --silent Be silent; don't output anything -v, --verbose Enable verbose output when executing commands Use \"newt [command] --help\" for more information about a command. Installing Newt from the Master Branch We recommend that you use the latest stable release version (1.0.0) of newt. If you would like to use the master branch with the latest updates, you can install newt from the HEAD of the master branch. ** Notes: ** The master branch may be unstable. This installation will install the latest version of Go on your computer, if it is not installed, and compile newt locally. If you previously installed newt using brew, unlink the current version: $brew unlink mynewt-newt Install the latest unstable version of newt from the master branch: $brew install --HEAD mynewt-newt ==> Installing mynewt-newt from runtimeco/mynewt ==> Cloning https://github.com/apache/incubator-mynewt-newt.git Cloning into 'Users/<username>/Library/Caches/Homebrew/mynewt-newt--git'... remote: Counting objects: 623, done. remote: Compressing objects: 100% (501/501), done. remote: Total 623 (delta 154), reused 323 (delta 84), pack-reused 0 Receiving objects: 100% (623/623), 1.10 MiB | 0 bytes/s, done. Resolving deltas: 100% (154/154), done. ==> Checking out branch master ==> go install \ud83c\udf7a /usr/local/Cellar/mynewt-newt/HEAD-409f7d3: 3 files, 10.4MB, built in 10 seconds $newt version Apache Newt (incubating) version: 1.0.0-dev To switch back to the stable release version (1.0.0) of newt, you can run: $brew switch mynewt-newt 1.0.0 Cleaning /usr/local/Cellar/mynewt-newt/1.0.0 Cleaning /usr/local/Cellar/mynewt-newt/HEAD-409f7d3 1 links created for /usr/local/Cellar/mynewt-newt/1.0.0 $newt version Apache Newt (incubating) version: 1.0.0","title":"Install Newt on Mac"},{"location":"newt/install/newt_mac/#installing-newt-on-mac-os","text":"Newt is supported on Mac OS X 64 bit platforms and has been tested on Mac OS 10.9 and higher. This page shows you how to install the following versions of newt: The latest stable release version (1.0.0) The latest from the master branch (unstable) Note: If you would like to contribute to the newt tool, see Setting Up Go Environment to Contribute to Newt and Newtmgr Tools .","title":"Installing Newt on Mac OS"},{"location":"newt/install/newt_mac/#installing-homebrew","text":"If you do not have Homebrew installed, run the following command. You will be prompted for your sudo password. $ ruby -e \"$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)\" You can also extract (or git clone ) Homebrew and install it to /usr/local.","title":"Installing Homebrew"},{"location":"newt/install/newt_mac/#installing-newt","text":"Add the ** runtimeco/homebrew-mynewt ** tap: $brew tap runtimeco/homebrew-mynewt $brew update","title":"Installing Newt"},{"location":"newt/install/newt_mac/#installing-the-latest-release-version-of-newt","text":"Install the latest stable release version (1.0.0) of newt: $brew install mynewt-newt ==> Installing mynewt-newt from runtimeco/mynewt ==> Downloading https://github.com/runtimeco/binary-releases/raw/master/mynewt-newt-tools_1.0.0/mynewt-newt-1.0.0.mavericks.bottle.tar.gz ==> Downloading from https://raw.githubusercontent.com/runtimeco/binary-releases/master/mynewt-newt-tools_1.0.0/mynewt-newt-1.0.0.mavericks. ######################################################################## 100.0% ==> Pouring mynewt-newt-1.0.0.mavericks.bottle.tar.gz \ud83c\udf7a /usr/local/Cellar/mynewt-newt/1.0.0: 3 files, 10.4MB Note: This installs the newt 1.0.0 binary that has been tested on Mac OS 10.9 and higher. If you are running an earlier version of Mac OS, the installation will install the latest version of Go and compile newt locally. Check that you are using the installed version of newt: $which newt /usr/local/bin/newt $ls -l /usr/local/bin/newt lrwxr-xr-x 1 user staff 36 Apr 15 08:18 /usr/local/bin/newt -> ../Cellar/mynewt-newt/1.0.0/bin/newt $newt version Apache Newt (incubating) version: 1.0.0 Note: If you previously built newt from source and the output of which newt shows \"$GOPATH/bin/newt\", you will need to move \"$GOPATH/bin\" after \"/usr/local/bin\" in your $PATH. Get information about newt: $newt help Newt allows you to create your own embedded application based on the Mynewt operating system. Newt provides both build and package management in a single tool, which allows you to compose an embedded application, and set of projects, and then build the necessary artifacts from those projects. For more information on the Mynewt operating system, please visit https://mynewt.apache.org/. Please use the newt help command, and specify the name of the command you want help for, for help on how to use a specific command Usage: newt [flags] newt [command] Examples: newt newt help [<command-name>] For help on <command-name>. If not specified, print this message. Available Commands: build Build one or more targets clean Delete build artifacts for one or more targets create-image Add image header to target binary debug Open debugger session to target info Show project info install Install project dependencies load Load built target to board mfg Manufacturing flash image commands new Create a new project pkg Create and manage packages in the current workspace run build/create-image/download/debug <target> size Size of target components sync Synchronize project dependencies target Commands to create, delete, configure, and query targets test Executes unit tests for one or more packages upgrade Upgrade project dependencies vals Display valid values for the specified element type(s) version Display the Newt version number Flags: -h, --help Help for newt commands -j, --jobs int Number of concurrent build jobs (default 8) -l, --loglevel string Log level (default \"WARN\") -o, --outfile string Filename to tee output to -q, --quiet Be quiet; only display error output -s, --silent Be silent; don't output anything -v, --verbose Enable verbose output when executing commands Use \"newt [command] --help\" for more information about a command.","title":"Installing the Latest Release Version of Newt"},{"location":"newt/install/newt_mac/#installing-newt-from-the-master-branch","text":"We recommend that you use the latest stable release version (1.0.0) of newt. If you would like to use the master branch with the latest updates, you can install newt from the HEAD of the master branch. ** Notes: ** The master branch may be unstable. This installation will install the latest version of Go on your computer, if it is not installed, and compile newt locally. If you previously installed newt using brew, unlink the current version: $brew unlink mynewt-newt Install the latest unstable version of newt from the master branch: $brew install --HEAD mynewt-newt ==> Installing mynewt-newt from runtimeco/mynewt ==> Cloning https://github.com/apache/incubator-mynewt-newt.git Cloning into 'Users/<username>/Library/Caches/Homebrew/mynewt-newt--git'... remote: Counting objects: 623, done. remote: Compressing objects: 100% (501/501), done. remote: Total 623 (delta 154), reused 323 (delta 84), pack-reused 0 Receiving objects: 100% (623/623), 1.10 MiB | 0 bytes/s, done. Resolving deltas: 100% (154/154), done. ==> Checking out branch master ==> go install \ud83c\udf7a /usr/local/Cellar/mynewt-newt/HEAD-409f7d3: 3 files, 10.4MB, built in 10 seconds $newt version Apache Newt (incubating) version: 1.0.0-dev To switch back to the stable release version (1.0.0) of newt, you can run: $brew switch mynewt-newt 1.0.0 Cleaning /usr/local/Cellar/mynewt-newt/1.0.0 Cleaning /usr/local/Cellar/mynewt-newt/HEAD-409f7d3 1 links created for /usr/local/Cellar/mynewt-newt/1.0.0 $newt version Apache Newt (incubating) version: 1.0.0","title":"Installing Newt from the Master Branch"},{"location":"newt/install/newt_windows/","text":"Installing Newt on Windows You can develop and build Mynewt OS applications for your target boards on the Windows platform. This page shows you how to build the newt tool from the lastest source on the master branch of the Mynewt newt git repository . The tool is written in Go (golang). In Windows, we use MinGW as the development environment to build and run Mynewt OS applications for target boards. MinGW runs the bash shell and provides a Unix-like environment. This provides a uniform way to build Mynewt OS applications. The Mynewt documentation and tutorials use Unix commands and you can use the same Unix commands on MinGW to follow the tutorials. The documentation will note any commands or behaviors that are specific to Windows. This guide shows you how to perform the following: Install MSYS2/MinGW. Install Git. Install Go. Setup the Go environment. Download the source, build, and install the newt tool. Step 1: Installing MSYS2/MinGW MSYS2/MinGW provides a bash shell and tools to build applications that run on Windows. It includes three subsystems: MSYS2 toolchain to build POSIX applications that run on Windows. MinGW32 toolchains to build 32 bit native Windows applications. MinGW64 toolchains to build 64 bit native Windows applications. The subsystems run the bash shell and provide a Unix-like environment. You can also run Windows applications from the shell. We will use the MinGW subsystem. Note: You can skip this installation step if you already have MinGW installed (from an earlier MSYS2/MinGW or Git Bash installation), but you must list the bin path for your installation in your Windows Path. For example: if you installed MSYS2/MinGW in the ** C:\\msys64 ** directory, add C:\\msys64\\usr\\bin to your Windows Path. If you are using Windows 10 WSL, ensure that you use the C:\\msys64\\usr\\bin\\bash.exe and not the Windows 10 WSL bash. To install and setup MSYS2 and MinGW: Download and run the MSYS2 installer . Select the 64 bit version if you are running on a 64 bit platform. Follow the prompts and check the Run MSYS2 now checkbox on the Installation Complete dialog. In the MSYS2 terminal, run the pacman -Syuu command. If you get a message to run the update again, close the terminal and run the pacman -Syuu command in a new terminal. To start a new MSYS2 terminal, select the \"MSYS2 MSYS\" application from the Windows start menu. Add a new user variable named MSYS2_PATH_TYPE and set the value to inherit in your Windows environment. This enables the MSYS2 and MinGW bash to inherit your Windows user Path values. To add the variable, select properties for your computer > Advanced system settings > Environment Variables > New Add the MinGW bin path to your Windows Path. For example: if you install MSYS2/MinGW in the C:\\msys64 directory, add C:\\msys64\\usr\\bin to your Windows Path. Note: If you are using Windows 10 WSL, ensure that you use the C:\\msys64\\usr\\bin\\bash.exe and not the Windows 10 WSL bash. Run the pacman -Su vim command to install the vim editor. Note: You can also use a Windows editor. You can access your files from the C:\\<msys-install-folder>\\home\\<username> folder, where msys-install-folder is the folder you installed MSYS2 in. For example, if you installed MSYS2 in the msys64 folder, your files are stored in C:\\msys64\\home\\<username> You will need to start a MinGW terminal to run the commands specified in the Mynewt documentation and tutorials. To start a MinGW terminal, select the \"MSYS2 Mingw\" application from the start Menu (you can use either MinGW32 or MinGW64). In Windows, we use the MingGW subsystem to build Mynewt tools and applications. Step 2: Installing Git for Windows Download and install Git for Windows if it is not already installed. Step 3: Installing Go Download and install the latest version of Go . Newt requires Go version 1.7 or higher. Step 4: Setting Up Your Go Environment This section describes the Go environment and how to setup a Go workspace. Go provides an environment to compile Go code, construct Go packages, and import Go code. You will use Go commands to import the newt package repository into your local Go environment. The Go language environment dictates a specific directory structure, or workspace in Go parlance. It must contain three sibling directories with the names src , pkg and bin : src contains Go source files organized into packages (one package per directory) pkg contains package objects bin contains the Go application executables that Go builds and installs. The GOPATH environment variable specifies the location of your workspace. To setup this workspace environment, create a dev directory and then a go directory under it. Set the GOPATH environment variable to this directory where you will clone the newt repository. Start up a MinGW terminal and run the following commands to set up your Go workspace: $ cd $HOME $ mkdir -p dev/go $ cd dev/go $ export GOPATH=`pwd` Add the following export statements to your ~/.bash_profile file and source the file: export GOPATH=$HOME/dev/go export PATH=$GOPATH/bin:$PATH Step 5: Downloading the Source and Installing the Newt Tool The newt Go package is mynewt.apache.org/newt/newt and is stored in the Apache Mynewt newt tool repository mirrored on github . We use the go get command to download the source, build, and install the newt tool binary in the $GOPATH/bin directory. Download the newt package source and install the tool: $cd $GOPATH $go get mynewt.apache.org/newt/newt $cd $GOPATH/src/mynewt.apache.org/newt $ls DISCLAIMER RELEASE_NOTES.md util INSTALLING.md build.sh viper LICENSE newt yaml NOTICE newtmgr README.md newtvm Check that the newt tool is installed and it is in your path: $ls $GOPATH/bin/newt ~/dev/go/bin/newt $which newt ~/dev/go/bin/newt $ newt version Apache Newt (incubating) version: 1.0.0-dev Get information about the newt tool: $newt Newt allows you to create your own embedded application based on the Mynewt operating system. Newt provides both build and package management in a single tool, which allows you to compose an embedded application, and set of projects, and then build the necessary artifacts from those projects. For more information on the Mynewt operating system, please visit https://mynewt.apache.org/. Please use the newt help command, and specify the name of the command you want help for, for help on how to use a specific command Usage: newt [flags] newt [command] Examples: newt newt help [<command-name>] For help on <command-name>. If not specified, print this message. Available Commands: build Build one or more targets clean Delete build artifacts for one or more targets create-image Add image header to target binary debug Open debugger session to target info Show project info install Install project dependencies load Load built target to board mfg Manufacturing flash image commands new Create a new project pkg Create and manage packages in the current workspace run build/create-image/download/debug <target> size Size of target components sync Synchronize project dependencies target Commands to create, delete, configure, and query targets test Executes unit tests for one or more packages upgrade Upgrade project dependencies vals Display valid values for the specified element type(s) version Display the Newt version number Flags: -h, --help Help for newt commands -j, --jobs int Number of concurrent build jobs (default 4) -l, --loglevel string Log level (default \"WARN\") -o, --outfile string Filename to tee output to -q, --quiet Be quiet; only display error output -s, --silent Be silent; don't output anything -v, --verbose Enable verbose output when executing commands Use \"newt [command] --help\" for more information about a command.","title":"Install Newt on Windows"},{"location":"newt/install/newt_windows/#installing-newt-on-windows","text":"You can develop and build Mynewt OS applications for your target boards on the Windows platform. This page shows you how to build the newt tool from the lastest source on the master branch of the Mynewt newt git repository . The tool is written in Go (golang). In Windows, we use MinGW as the development environment to build and run Mynewt OS applications for target boards. MinGW runs the bash shell and provides a Unix-like environment. This provides a uniform way to build Mynewt OS applications. The Mynewt documentation and tutorials use Unix commands and you can use the same Unix commands on MinGW to follow the tutorials. The documentation will note any commands or behaviors that are specific to Windows. This guide shows you how to perform the following: Install MSYS2/MinGW. Install Git. Install Go. Setup the Go environment. Download the source, build, and install the newt tool.","title":"Installing Newt on Windows"},{"location":"newt/install/newt_windows/#step-1-installing-msys2mingw","text":"MSYS2/MinGW provides a bash shell and tools to build applications that run on Windows. It includes three subsystems: MSYS2 toolchain to build POSIX applications that run on Windows. MinGW32 toolchains to build 32 bit native Windows applications. MinGW64 toolchains to build 64 bit native Windows applications. The subsystems run the bash shell and provide a Unix-like environment. You can also run Windows applications from the shell. We will use the MinGW subsystem. Note: You can skip this installation step if you already have MinGW installed (from an earlier MSYS2/MinGW or Git Bash installation), but you must list the bin path for your installation in your Windows Path. For example: if you installed MSYS2/MinGW in the ** C:\\msys64 ** directory, add C:\\msys64\\usr\\bin to your Windows Path. If you are using Windows 10 WSL, ensure that you use the C:\\msys64\\usr\\bin\\bash.exe and not the Windows 10 WSL bash. To install and setup MSYS2 and MinGW: Download and run the MSYS2 installer . Select the 64 bit version if you are running on a 64 bit platform. Follow the prompts and check the Run MSYS2 now checkbox on the Installation Complete dialog. In the MSYS2 terminal, run the pacman -Syuu command. If you get a message to run the update again, close the terminal and run the pacman -Syuu command in a new terminal. To start a new MSYS2 terminal, select the \"MSYS2 MSYS\" application from the Windows start menu. Add a new user variable named MSYS2_PATH_TYPE and set the value to inherit in your Windows environment. This enables the MSYS2 and MinGW bash to inherit your Windows user Path values. To add the variable, select properties for your computer > Advanced system settings > Environment Variables > New Add the MinGW bin path to your Windows Path. For example: if you install MSYS2/MinGW in the C:\\msys64 directory, add C:\\msys64\\usr\\bin to your Windows Path. Note: If you are using Windows 10 WSL, ensure that you use the C:\\msys64\\usr\\bin\\bash.exe and not the Windows 10 WSL bash. Run the pacman -Su vim command to install the vim editor. Note: You can also use a Windows editor. You can access your files from the C:\\<msys-install-folder>\\home\\<username> folder, where msys-install-folder is the folder you installed MSYS2 in. For example, if you installed MSYS2 in the msys64 folder, your files are stored in C:\\msys64\\home\\<username> You will need to start a MinGW terminal to run the commands specified in the Mynewt documentation and tutorials. To start a MinGW terminal, select the \"MSYS2 Mingw\" application from the start Menu (you can use either MinGW32 or MinGW64). In Windows, we use the MingGW subsystem to build Mynewt tools and applications.","title":"Step 1: Installing MSYS2/MinGW"},{"location":"newt/install/newt_windows/#step-2-installing-git-for-windows","text":"Download and install Git for Windows if it is not already installed.","title":"Step 2: Installing Git for Windows"},{"location":"newt/install/newt_windows/#step-3-installing-go","text":"Download and install the latest version of Go . Newt requires Go version 1.7 or higher.","title":"Step 3: Installing Go"},{"location":"newt/install/newt_windows/#step-4-setting-up-your-go-environment","text":"This section describes the Go environment and how to setup a Go workspace. Go provides an environment to compile Go code, construct Go packages, and import Go code. You will use Go commands to import the newt package repository into your local Go environment. The Go language environment dictates a specific directory structure, or workspace in Go parlance. It must contain three sibling directories with the names src , pkg and bin : src contains Go source files organized into packages (one package per directory) pkg contains package objects bin contains the Go application executables that Go builds and installs. The GOPATH environment variable specifies the location of your workspace. To setup this workspace environment, create a dev directory and then a go directory under it. Set the GOPATH environment variable to this directory where you will clone the newt repository. Start up a MinGW terminal and run the following commands to set up your Go workspace: $ cd $HOME $ mkdir -p dev/go $ cd dev/go $ export GOPATH=`pwd` Add the following export statements to your ~/.bash_profile file and source the file: export GOPATH=$HOME/dev/go export PATH=$GOPATH/bin:$PATH","title":"Step 4: Setting Up Your Go Environment"},{"location":"newt/install/newt_windows/#step-5-downloading-the-source-and-installing-the-newt-tool","text":"The newt Go package is mynewt.apache.org/newt/newt and is stored in the Apache Mynewt newt tool repository mirrored on github . We use the go get command to download the source, build, and install the newt tool binary in the $GOPATH/bin directory. Download the newt package source and install the tool: $cd $GOPATH $go get mynewt.apache.org/newt/newt $cd $GOPATH/src/mynewt.apache.org/newt $ls DISCLAIMER RELEASE_NOTES.md util INSTALLING.md build.sh viper LICENSE newt yaml NOTICE newtmgr README.md newtvm Check that the newt tool is installed and it is in your path: $ls $GOPATH/bin/newt ~/dev/go/bin/newt $which newt ~/dev/go/bin/newt $ newt version Apache Newt (incubating) version: 1.0.0-dev Get information about the newt tool: $newt Newt allows you to create your own embedded application based on the Mynewt operating system. Newt provides both build and package management in a single tool, which allows you to compose an embedded application, and set of projects, and then build the necessary artifacts from those projects. For more information on the Mynewt operating system, please visit https://mynewt.apache.org/. Please use the newt help command, and specify the name of the command you want help for, for help on how to use a specific command Usage: newt [flags] newt [command] Examples: newt newt help [<command-name>] For help on <command-name>. If not specified, print this message. Available Commands: build Build one or more targets clean Delete build artifacts for one or more targets create-image Add image header to target binary debug Open debugger session to target info Show project info install Install project dependencies load Load built target to board mfg Manufacturing flash image commands new Create a new project pkg Create and manage packages in the current workspace run build/create-image/download/debug <target> size Size of target components sync Synchronize project dependencies target Commands to create, delete, configure, and query targets test Executes unit tests for one or more packages upgrade Upgrade project dependencies vals Display valid values for the specified element type(s) version Display the Newt version number Flags: -h, --help Help for newt commands -j, --jobs int Number of concurrent build jobs (default 4) -l, --loglevel string Log level (default \"WARN\") -o, --outfile string Filename to tee output to -q, --quiet Be quiet; only display error output -s, --silent Be silent; don't output anything -v, --verbose Enable verbose output when executing commands Use \"newt [command] --help\" for more information about a command.","title":"Step 5: Downloading the Source and Installing the Newt Tool"},{"location":"newtmgr/install_linux/","text":"Installing Newtmgr on Linux You can install the latest stable release (1.0.0) of the newtmgr tool from a Debian binary package (amd64) or from a Debian source package. This page shows you how to: Set up your computer to retrieve Debian packages from the runtimeco debian package repository. Note: You can skip this step if you already set up your computer to access the runtimeco debian repository when you installed the newt tool. Install the latest stable release version of newtmgr from a Debian binary package. Install the latest stable release version of newtmgr from a Debian source package. If you are installing on an amd64 platform, we recommend that you install from the binary package. Note: We have tested the newtmgr tool binary and apt-get install from the runtimeco Debian package repository for Ubuntu version 16. Earlier Ubuntu versions (for example: Ubuntu 14) may have incompatibility with the repository. We recommend that you upgrade Ubuntu on your computer. Note: See Setting Up an Go Environment to Contribute to Newt and Newtmgr Tools if you want to: Use the newtmgr tool with the latest updates from the master branch. The master branch may be unstable and we recommend that you use the latest stable release version. Contribute to the newtmgr tool. Setting Up Your Computer to Get Packages from runtimeco The newtmgr Debian packages are stored in a private repository on https://github/runtimeco/debian-mynewt . You must set up the following on your computer to retreive packages from the repository: Note : You only need to perform this setup once on your computer and you may have already done so when you installed the newt tool. Install the apt-transport-https package to use HTTPS to retrieve packages. Download the public key for the runtimeco debian repository and import the key into the apt keychain. Add the repository for the binary and source packages to the apt source list. Install the apt-transport-https package: $sudo apt-get update $sudo apt-get install apt-transport-https Download the public key for the runtimeco apt repo ( Note: There is a - after apt-key add ): wget -qO - https://raw.githubusercontent.com/runtimeco/debian-mynewt/master/mynewt.gpg.key | sudo apt-key add - Add the repository for the binary and source packages to the mynewt.list apt source list file. $sudo -s [sudo] password for <user>: root$ cat > /etc/apt/sources.list.d/mynewt.list <<EOF deb https://raw.githubusercontent.com/runtimeco/debian-mynewt/master latest main deb-src https://raw.githubusercontent.com/runtimeco/debian-mynewt/master latest main EOF root$exit Note: Do not forget to exit the root shell. Verify the content of the source list file: $more /etc/apt/sources.list.d/mynewt.list deb https://raw.githubusercontent.com/runtimeco/debian-mynewt/master latest main deb-src https://raw.githubusercontent.com/runtimeco/debian-mynewt/master latest main Update the available packages: $sudo apt-get update Note: If you are not using Ubuntu version 16, you may see the following errors. We recommend that you upgrade Ubuntu. We have provided instructions on how to manually download and install the binary package if you choose not to upgrade, but you will want to upgrade Ubuntu if you are installing from source. W: Failed to fetch https://raw.githubusercontent.com/runtimeco/debian-mynewt/master/dists/latest/main/source/Sources Ht tpError404 W: Failed to fetch https://raw.githubusercontent.com/runtimeco/debian-mynewt/master/dists/latest/main/binary-amd64/Packa ges Bad header line W: Failed to fetch https://raw.githubusercontent.com/runtimeco/debian-mynewt/master/dists/latest/main/binary-i386/Packag es HttpError404 E: Some index files failed to download. They have been ignored, or old ones used instead. Installing the Latest Release of Newtmgr from a Binary Package For Linux amd64 platforms, you can install the latest stable version (1.0.0) of newtmgr from the newtmgr Debian binary package: $sudo apt-get install newtmgr Reading package lists... Done Building dependency tree Reading state information... Done The following NEW packages will be installed: newtmgr 0 upgraded, 1 newly installed, 0 to remove and 204 not upgraded. Need to get 0 B/2,312 kB of archives. After this operation, 11.5 MB of additional disk space will be used. Selecting previously unselected package newtmgr. (Reading database ... 211647 files and directories currently installed.) Preparing to unpack .../newtmgr_1.0.0-1_amd64.deb ... Unpacking newtmgr (1.0.0-1) ... Setting up newtmgr (1.0.0-1) Note: If you are not using Ubuntu version 16 and are not able to update the runtimeco Debian package repo on your computer successfully, you can manually download and install the newtmgr_1.0.0-1_amd64.deb binary package as follows: $wget https://raw.githubusercontent.com/runtimeco/debian-mynewt/master/pool/main/n/newtmgr/newtmgr_1.0.0-1_amd64.deb $sudo dpkg -i newtmgr_1.0.0-1_amd64.deb See Checking the Installed Version of Newtmgr to verify that you are using the installed version of newtmgr. Installing the Latest Stable Release of Newtmgr from a Source Package If you are running Linux on a different architecture, you can install the Debian source package for the latest stable release (1.0.0) of newtmgr. The installation of the source package builds the newtmgr binary and creates a Debian binary package that you then install. Note : Newtmgr version 1.0.0 has been tested on Linux amd64 platforms. Installing Go 1.7 You need Go version 1.7 or higher to build Newtmgr version 1.0.0. Currently, the latest Go version that Ubuntu installs is 1.6. Run go version to check if you have Go 1.7 installed. Install Go version 1.7: $sudo apt-get install golang-1.7-go Reading package lists... Done ... Unpacking golang-1.7-go (1.7.1-2ubuntu1) ... Setting up golang-1.7-go (1.7.1-2ubuntu1) ... $ $sudo ln -sf ../lib/go-1.7/bin/go /usr/bin/go $go version go version go1.7.1 linux/amd64 You can also download version 1.7 from https://golang.org/dl/ . Installing from the Source Package Create a directory and change into the directory, download the source package, and build a binary package from the source package: mkdir newtmgr_source $cd newtmgr_source $sudo apt-get --build source newtmgr [sudo] password for <user>: sudo apt-get --build source newtmgr Reading package lists... Done Need to get 1,867 kB of source archives. Get:1 https://raw.githubusercontent.com/runtimeco/debian-mynewt/master latest/main newtmgr 1.0.0-1 (dsc) [822 B] Get:2 https://raw.githubusercontent.com/runtimeco/debian-mynewt/master latest/main newtmgr 1.0.0-1 (tar) [1,864 kB] Get:3 https://raw.githubusercontent.com/runtimeco/debian-mynewt/master latest/main newtmgr 1.0.0-1 (diff) [2,372 B] Fetched 1,867 kB in 1s (1,767 kB/s) ... dpkg-deb: building package 'newtmgr' in '../newtmgr_1.0.0-1_amd64.deb'. dpkg-genchanges --build=any,all >../newtmgr_1.0.0-1_amd64.changes dpkg-genchanges: info: binary-only upload (no source code included) dpkg-source --after-build newtmgr-1.0.0 dpkg-buildpackage: info: binary-only upload (no source included) W: Can't drop privileges for downloading as file 'newtmgr_1.0.0-1.dsc' couldn't be accessed by user '_apt'. - pkgAcquire::Run (13: Permission denied) Note: You can ignore the \"Permission denied\" warning message at the end of the command. Install the newtmgr binary package that is created from the source package: Note: The file name for the binary package has the format: newtmgr_1.0.0-1_ arch .deb, where arch is a value that identifies your host architecture. $sudo dpkg -i newtmgr_1.0.0-1_amd64.deb Selecting previously unselected package newtmgr. (Reading database ... 215099 files and directories currently installed.) Preparing to unpack newtmgr_1.0.0-1_amd64.deb ... Unpacking newtmgr (1.0.0-1) ... Setting up newtmgr (1.0.0-1) ... Checking the Installed Version of Newtmgr After you have installed newtmgr from either a Debian binary or source package, check that you are using the installed version of newtmgr from /usr/bin . Check the modification time of the binary and the newtmgr tool that you are using: $ls -l /usr/bin/newtmgr -rwxr-xr-x 1 root root 11473328 Apr 25 10:10 /usr/bin/newtmgr $which newtmgr /usr/bin/newtmgr Note: If you previously built newtmgr from source and the output of which newtmgr shows \"$GOPATH/bin/newtmgr\", you will need to move \"$GOPATH/bin\" after \"/usr/bin\" for your PATH environment variable and export it. Get information about newtmgr: $newtmgr Newtmgr helps you manage remote devices running the Mynewt OS Usage: newtmgr [flags] newtmgr [command] Available Commands: config Read or write a config value on a device conn Manage newtmgr connection profiles crash Send a crash command to a device datetime Manage datetime on a device echo Send data to a device and display the echoed back data fs Access files on a device image Manage images on a device log Manage logs on a device mpstats Read memory pool statistics from a device reset Send reset request to a device run Run test procedures on a device stat Read statistics from a device taskstats Read task statistics from a device Flags: -c, --conn string connection profile to use -h, --help Help for newtmgr commands -l, --loglevel string log level to use (default \"info\") -t, --trace print all bytes transmitted and received Use \"newtmgr [command] --help\" for more information about a command. ```","title":"Install Newtmgr On Linux"},{"location":"newtmgr/install_linux/#installing-newtmgr-on-linux","text":"You can install the latest stable release (1.0.0) of the newtmgr tool from a Debian binary package (amd64) or from a Debian source package. This page shows you how to: Set up your computer to retrieve Debian packages from the runtimeco debian package repository. Note: You can skip this step if you already set up your computer to access the runtimeco debian repository when you installed the newt tool. Install the latest stable release version of newtmgr from a Debian binary package. Install the latest stable release version of newtmgr from a Debian source package. If you are installing on an amd64 platform, we recommend that you install from the binary package. Note: We have tested the newtmgr tool binary and apt-get install from the runtimeco Debian package repository for Ubuntu version 16. Earlier Ubuntu versions (for example: Ubuntu 14) may have incompatibility with the repository. We recommend that you upgrade Ubuntu on your computer. Note: See Setting Up an Go Environment to Contribute to Newt and Newtmgr Tools if you want to: Use the newtmgr tool with the latest updates from the master branch. The master branch may be unstable and we recommend that you use the latest stable release version. Contribute to the newtmgr tool.","title":"Installing Newtmgr on Linux"},{"location":"newtmgr/install_linux/#setting-up-your-computer-to-get-packages-from-runtimeco","text":"The newtmgr Debian packages are stored in a private repository on https://github/runtimeco/debian-mynewt . You must set up the following on your computer to retreive packages from the repository: Note : You only need to perform this setup once on your computer and you may have already done so when you installed the newt tool. Install the apt-transport-https package to use HTTPS to retrieve packages. Download the public key for the runtimeco debian repository and import the key into the apt keychain. Add the repository for the binary and source packages to the apt source list. Install the apt-transport-https package: $sudo apt-get update $sudo apt-get install apt-transport-https Download the public key for the runtimeco apt repo ( Note: There is a - after apt-key add ): wget -qO - https://raw.githubusercontent.com/runtimeco/debian-mynewt/master/mynewt.gpg.key | sudo apt-key add - Add the repository for the binary and source packages to the mynewt.list apt source list file. $sudo -s [sudo] password for <user>: root$ cat > /etc/apt/sources.list.d/mynewt.list <<EOF deb https://raw.githubusercontent.com/runtimeco/debian-mynewt/master latest main deb-src https://raw.githubusercontent.com/runtimeco/debian-mynewt/master latest main EOF root$exit Note: Do not forget to exit the root shell. Verify the content of the source list file: $more /etc/apt/sources.list.d/mynewt.list deb https://raw.githubusercontent.com/runtimeco/debian-mynewt/master latest main deb-src https://raw.githubusercontent.com/runtimeco/debian-mynewt/master latest main Update the available packages: $sudo apt-get update Note: If you are not using Ubuntu version 16, you may see the following errors. We recommend that you upgrade Ubuntu. We have provided instructions on how to manually download and install the binary package if you choose not to upgrade, but you will want to upgrade Ubuntu if you are installing from source. W: Failed to fetch https://raw.githubusercontent.com/runtimeco/debian-mynewt/master/dists/latest/main/source/Sources Ht tpError404 W: Failed to fetch https://raw.githubusercontent.com/runtimeco/debian-mynewt/master/dists/latest/main/binary-amd64/Packa ges Bad header line W: Failed to fetch https://raw.githubusercontent.com/runtimeco/debian-mynewt/master/dists/latest/main/binary-i386/Packag es HttpError404 E: Some index files failed to download. They have been ignored, or old ones used instead.","title":"Setting Up Your Computer to Get Packages from runtimeco"},{"location":"newtmgr/install_linux/#installing-the-latest-release-of-newtmgr-from-a-binary-package","text":"For Linux amd64 platforms, you can install the latest stable version (1.0.0) of newtmgr from the newtmgr Debian binary package: $sudo apt-get install newtmgr Reading package lists... Done Building dependency tree Reading state information... Done The following NEW packages will be installed: newtmgr 0 upgraded, 1 newly installed, 0 to remove and 204 not upgraded. Need to get 0 B/2,312 kB of archives. After this operation, 11.5 MB of additional disk space will be used. Selecting previously unselected package newtmgr. (Reading database ... 211647 files and directories currently installed.) Preparing to unpack .../newtmgr_1.0.0-1_amd64.deb ... Unpacking newtmgr (1.0.0-1) ... Setting up newtmgr (1.0.0-1) Note: If you are not using Ubuntu version 16 and are not able to update the runtimeco Debian package repo on your computer successfully, you can manually download and install the newtmgr_1.0.0-1_amd64.deb binary package as follows: $wget https://raw.githubusercontent.com/runtimeco/debian-mynewt/master/pool/main/n/newtmgr/newtmgr_1.0.0-1_amd64.deb $sudo dpkg -i newtmgr_1.0.0-1_amd64.deb See Checking the Installed Version of Newtmgr to verify that you are using the installed version of newtmgr.","title":"Installing the Latest Release of Newtmgr from a Binary Package"},{"location":"newtmgr/install_linux/#installing-the-latest-stable-release-of-newtmgr-from-a-source-package","text":"If you are running Linux on a different architecture, you can install the Debian source package for the latest stable release (1.0.0) of newtmgr. The installation of the source package builds the newtmgr binary and creates a Debian binary package that you then install. Note : Newtmgr version 1.0.0 has been tested on Linux amd64 platforms.","title":"Installing the Latest Stable Release of Newtmgr from a Source Package"},{"location":"newtmgr/install_linux/#installing-go-17","text":"You need Go version 1.7 or higher to build Newtmgr version 1.0.0. Currently, the latest Go version that Ubuntu installs is 1.6. Run go version to check if you have Go 1.7 installed. Install Go version 1.7: $sudo apt-get install golang-1.7-go Reading package lists... Done ... Unpacking golang-1.7-go (1.7.1-2ubuntu1) ... Setting up golang-1.7-go (1.7.1-2ubuntu1) ... $ $sudo ln -sf ../lib/go-1.7/bin/go /usr/bin/go $go version go version go1.7.1 linux/amd64 You can also download version 1.7 from https://golang.org/dl/ .","title":"Installing Go 1.7"},{"location":"newtmgr/install_linux/#installing-from-the-source-package","text":"Create a directory and change into the directory, download the source package, and build a binary package from the source package: mkdir newtmgr_source $cd newtmgr_source $sudo apt-get --build source newtmgr [sudo] password for <user>: sudo apt-get --build source newtmgr Reading package lists... Done Need to get 1,867 kB of source archives. Get:1 https://raw.githubusercontent.com/runtimeco/debian-mynewt/master latest/main newtmgr 1.0.0-1 (dsc) [822 B] Get:2 https://raw.githubusercontent.com/runtimeco/debian-mynewt/master latest/main newtmgr 1.0.0-1 (tar) [1,864 kB] Get:3 https://raw.githubusercontent.com/runtimeco/debian-mynewt/master latest/main newtmgr 1.0.0-1 (diff) [2,372 B] Fetched 1,867 kB in 1s (1,767 kB/s) ... dpkg-deb: building package 'newtmgr' in '../newtmgr_1.0.0-1_amd64.deb'. dpkg-genchanges --build=any,all >../newtmgr_1.0.0-1_amd64.changes dpkg-genchanges: info: binary-only upload (no source code included) dpkg-source --after-build newtmgr-1.0.0 dpkg-buildpackage: info: binary-only upload (no source included) W: Can't drop privileges for downloading as file 'newtmgr_1.0.0-1.dsc' couldn't be accessed by user '_apt'. - pkgAcquire::Run (13: Permission denied) Note: You can ignore the \"Permission denied\" warning message at the end of the command. Install the newtmgr binary package that is created from the source package: Note: The file name for the binary package has the format: newtmgr_1.0.0-1_ arch .deb, where arch is a value that identifies your host architecture. $sudo dpkg -i newtmgr_1.0.0-1_amd64.deb Selecting previously unselected package newtmgr. (Reading database ... 215099 files and directories currently installed.) Preparing to unpack newtmgr_1.0.0-1_amd64.deb ... Unpacking newtmgr (1.0.0-1) ... Setting up newtmgr (1.0.0-1) ...","title":"Installing from the Source Package"},{"location":"newtmgr/install_linux/#checking-the-installed-version-of-newtmgr","text":"After you have installed newtmgr from either a Debian binary or source package, check that you are using the installed version of newtmgr from /usr/bin . Check the modification time of the binary and the newtmgr tool that you are using: $ls -l /usr/bin/newtmgr -rwxr-xr-x 1 root root 11473328 Apr 25 10:10 /usr/bin/newtmgr $which newtmgr /usr/bin/newtmgr Note: If you previously built newtmgr from source and the output of which newtmgr shows \"$GOPATH/bin/newtmgr\", you will need to move \"$GOPATH/bin\" after \"/usr/bin\" for your PATH environment variable and export it. Get information about newtmgr: $newtmgr Newtmgr helps you manage remote devices running the Mynewt OS Usage: newtmgr [flags] newtmgr [command] Available Commands: config Read or write a config value on a device conn Manage newtmgr connection profiles crash Send a crash command to a device datetime Manage datetime on a device echo Send data to a device and display the echoed back data fs Access files on a device image Manage images on a device log Manage logs on a device mpstats Read memory pool statistics from a device reset Send reset request to a device run Run test procedures on a device stat Read statistics from a device taskstats Read task statistics from a device Flags: -c, --conn string connection profile to use -h, --help Help for newtmgr commands -l, --loglevel string log level to use (default \"info\") -t, --trace print all bytes transmitted and received Use \"newtmgr [command] --help\" for more information about a command. ```","title":" Checking the Installed Version of Newtmgr"},{"location":"newtmgr/install_mac/","text":"Installing Newtmgr on Mac OS Newtmgr is supported on Mac OS X 64 bit platforms and has been tested on Mac OS 10.9 and higher. This page shows you how to install the following versions of newtmgr: The latest stable release version (1.0.0) The latest from the master branch (unstable) Note: If you would like to contribute to the newtmgr tool, see Setting Up Go Environment to Contribute to Newt and Newtmgr Tools . Adding the runtimeco/homebrew-mynewt Tap: You should have added the runtimeco/homebrew-mynewt tap when you installed the newt tool. Run the following commands if you have not done so: $brew tap runtimeco/homebrew-mynewt $brew update Installing the Latest Release Version of Newtmgr Install the latest stable release version (1.0.0) of newtmgr: brew install mynewt-newtmgr ==> Installing mynewt-newtmgr from runtimeco/mynewt ==> Downloading https://github.com/runtimeco/binary-releases/raw/master/mynewt-newt-tools_1.0.0/mynewt-newtmgr-1.0.0.mavericks.bottle.tar.gz ==> Downloading from https://raw.githubusercontent.com/runtimeco/binary-releases/master/mynewt-newt-tools_1.0.0/mynewt-newtmgr-1.0.0.maveric ######################################################################## 100.0% ==> Pouring mynewt-newtmgr-1.0.0.mavericks.bottle.tar.gz \ud83c\udf7a /usr/local/Cellar/mynewt-newtmgr/1.0.0: 3 files, 15.2MB Note: This installs the newtmgr 1.0.0 binary that has been tested on Mac OS 10.9 and higher. If you are running an earlier version of Mac OS, the installation will install the latest version of Go and compile newtmgr locally. Check that you are using the installed version of newtmgr: $which newtmgr /usr/local/bin/newtmgr ls -l /usr/local/bin/newtmgr lrwxr-xr-x 1 user staff 42 Apr 15 09:14 /usr/local/bin/newtmgr -> ../Cellar/mynewt-newtmgr/1.0.0/bin/newtmgr Note: If you previously built newtmgr from source and the output of which newtmgr shows \"$GOPATH/bin/newtmgr\", you will need to move \"$GOPATH/bin\" after \"/usr/local/bin\" in your $PATH. Get information about newtmgr: $newtmgr help Newtmgr helps you manage remote devices running the Mynewt OS Usage: newtmgr [flags] newtmgr [command] Available Commands: config Read or write a config value on a device conn Manage newtmgr connection profiles crash Send a crash command to a device datetime Manage datetime on a device echo Send data to a device and display the echoed back data fs Access files on a device image Manage images on a device log Manage logs on a device mpstats Read memory pool statistics from a device reset Send reset request to a device run Run test procedures on a device stat Read statistics from a device taskstats Read task statistics from a device Flags: -c, --conn string connection profile to use -h, --help Help for newtmgr commands -l, --loglevel string log level to use (default \"info\") -t, --trace print all bytes transmitted and received Use \"newtmgr [command] --help\" for more information about a command. Installing Newtmgr from the Master Branch We recommend that you use the latest stable release version (1.0.0) of newtmgr. If you would like to use the master branch with the latest updates, you can install newtmgr from the HEAD of the master branch. ** Notes: ** The master branch may be unstable. This installation will install the latest version of Go on your computer, if it is not installed, and compile newtmgr locally. If you already installed newtgmr, unlink the current version: $brew unlink mynewt-newtmgr Install the latest unstable version of newtmgr from the master branch: $brew install --HEAD mynewt-newtmgr ==> Installing mynewt-newtmgr from runtimeco/mynewt ==> Cloning https://github.com/apache/incubator-mynewt-newt.git Cloning into '/Users/<user>/Library/Caches/Homebrew/mynewt-newtmgr--git'... remote: Counting objects: 623, done. remote: Compressing objects: 100% (501/501), done. remote: Total 623 (delta 154), reused 323 (delta 84), pack-reused 0 Receiving objects: 100% (623/623), 1.10 MiB | 0 bytes/s, done. Resolving deltas: 100% (154/154), done. ==> Checking out branch master ==> go install \ud83c\udf7a /usr/local/Cellar/mynewt-newtmgr/HEAD-409f7d3: 3 files, 15.1MB, built in 14 seconds To switch back to the stable release version (1.0.0) of newtmgr, you can run: $brew switch mynewt-newtmgr 1.0.0 Cleaning /usr/local/Cellar/mynewt-newtmgr/1.0.0 Cleaning /usr/local/Cellar/mynewt-newtmgr/HEAD-409f7d3 1 links created for /usr/local/Cellar/mynewt-newtmgr/1.0.0","title":"Install Newtmgr On Mac OS"},{"location":"newtmgr/install_mac/#installing-newtmgr-on-mac-os","text":"Newtmgr is supported on Mac OS X 64 bit platforms and has been tested on Mac OS 10.9 and higher. This page shows you how to install the following versions of newtmgr: The latest stable release version (1.0.0) The latest from the master branch (unstable) Note: If you would like to contribute to the newtmgr tool, see Setting Up Go Environment to Contribute to Newt and Newtmgr Tools .","title":"Installing Newtmgr on Mac OS"},{"location":"newtmgr/install_mac/#adding-the-runtimecohomebrew-mynewt-tap","text":"You should have added the runtimeco/homebrew-mynewt tap when you installed the newt tool. Run the following commands if you have not done so: $brew tap runtimeco/homebrew-mynewt $brew update","title":"Adding the runtimeco/homebrew-mynewt Tap:"},{"location":"newtmgr/install_mac/#installing-the-latest-release-version-of-newtmgr","text":"Install the latest stable release version (1.0.0) of newtmgr: brew install mynewt-newtmgr ==> Installing mynewt-newtmgr from runtimeco/mynewt ==> Downloading https://github.com/runtimeco/binary-releases/raw/master/mynewt-newt-tools_1.0.0/mynewt-newtmgr-1.0.0.mavericks.bottle.tar.gz ==> Downloading from https://raw.githubusercontent.com/runtimeco/binary-releases/master/mynewt-newt-tools_1.0.0/mynewt-newtmgr-1.0.0.maveric ######################################################################## 100.0% ==> Pouring mynewt-newtmgr-1.0.0.mavericks.bottle.tar.gz \ud83c\udf7a /usr/local/Cellar/mynewt-newtmgr/1.0.0: 3 files, 15.2MB Note: This installs the newtmgr 1.0.0 binary that has been tested on Mac OS 10.9 and higher. If you are running an earlier version of Mac OS, the installation will install the latest version of Go and compile newtmgr locally. Check that you are using the installed version of newtmgr: $which newtmgr /usr/local/bin/newtmgr ls -l /usr/local/bin/newtmgr lrwxr-xr-x 1 user staff 42 Apr 15 09:14 /usr/local/bin/newtmgr -> ../Cellar/mynewt-newtmgr/1.0.0/bin/newtmgr Note: If you previously built newtmgr from source and the output of which newtmgr shows \"$GOPATH/bin/newtmgr\", you will need to move \"$GOPATH/bin\" after \"/usr/local/bin\" in your $PATH. Get information about newtmgr: $newtmgr help Newtmgr helps you manage remote devices running the Mynewt OS Usage: newtmgr [flags] newtmgr [command] Available Commands: config Read or write a config value on a device conn Manage newtmgr connection profiles crash Send a crash command to a device datetime Manage datetime on a device echo Send data to a device and display the echoed back data fs Access files on a device image Manage images on a device log Manage logs on a device mpstats Read memory pool statistics from a device reset Send reset request to a device run Run test procedures on a device stat Read statistics from a device taskstats Read task statistics from a device Flags: -c, --conn string connection profile to use -h, --help Help for newtmgr commands -l, --loglevel string log level to use (default \"info\") -t, --trace print all bytes transmitted and received Use \"newtmgr [command] --help\" for more information about a command.","title":"Installing the Latest Release Version of Newtmgr"},{"location":"newtmgr/install_mac/#installing-newtmgr-from-the-master-branch","text":"We recommend that you use the latest stable release version (1.0.0) of newtmgr. If you would like to use the master branch with the latest updates, you can install newtmgr from the HEAD of the master branch. ** Notes: ** The master branch may be unstable. This installation will install the latest version of Go on your computer, if it is not installed, and compile newtmgr locally. If you already installed newtgmr, unlink the current version: $brew unlink mynewt-newtmgr Install the latest unstable version of newtmgr from the master branch: $brew install --HEAD mynewt-newtmgr ==> Installing mynewt-newtmgr from runtimeco/mynewt ==> Cloning https://github.com/apache/incubator-mynewt-newt.git Cloning into '/Users/<user>/Library/Caches/Homebrew/mynewt-newtmgr--git'... remote: Counting objects: 623, done. remote: Compressing objects: 100% (501/501), done. remote: Total 623 (delta 154), reused 323 (delta 84), pack-reused 0 Receiving objects: 100% (623/623), 1.10 MiB | 0 bytes/s, done. Resolving deltas: 100% (154/154), done. ==> Checking out branch master ==> go install \ud83c\udf7a /usr/local/Cellar/mynewt-newtmgr/HEAD-409f7d3: 3 files, 15.1MB, built in 14 seconds To switch back to the stable release version (1.0.0) of newtmgr, you can run: $brew switch mynewt-newtmgr 1.0.0 Cleaning /usr/local/Cellar/mynewt-newtmgr/1.0.0 Cleaning /usr/local/Cellar/mynewt-newtmgr/HEAD-409f7d3 1 links created for /usr/local/Cellar/mynewt-newtmgr/1.0.0","title":"Installing Newtmgr from the Master Branch"},{"location":"newtmgr/install_windows/","text":"Installing Newtmgr on Windows You can build and install the newtmgr tool from the latest source on the master branch. Newtmgr is a Go (golang) package. This guide shows you how to install the tool from source. It assumes that you already installed the newt tool on Windows and have the Windows development environment and Go workspace set up. Downloading and Installing the Newtmgr Tool The newtmgr Go package is mynewt.apache.org/newtmgr/newtmgr . It is stored in the Apache Mynewt newtmgr tool repository mirrored on github . Run the go get command, from your Go workspace, to download, build, and install the newtmgr tool: $cd $GOPATH $go get mynewt.apache.org/newtmgr/newtmgr $cd $GOPATH/src/mynewt.apache.org/newtmgr $ls DISCLAIMER NOTICE newtmgr LICENSE README.md nmxact $git status On branch master Your branch is up-to-date with 'origin/master'. nothing to commit, working directory clean Check that the newtmgr binary is installed and you are using the one from $GOPATH/bin : $ls $GOPATH/bin/newtmgr ~/dev/go/bin/newtmgr $which newtmgr ~/dev/go/bin/newtmgr Get information about the newtmgr tool: $newtmgr Newtmgr helps you manage remote devices running the Mynewt OS Usage: newtmgr [flags] newtmgr [command] Available Commands: config Read or write config value on target conn Manage newtmgr connection profiles crash Send crash command to remote endpoint using newtmgr datetime Manage datetime on the device echo Send data to remote endpoint using newtmgr, and receive data back fs Access files on device help Help about any command image Manage images on remote instance log Handles log on remote instance mpstat Read mempool statistics from a remote endpoint reset Performs a soft reset of target device run Run procedures on remote device stat Read statistics from a remote endpoint taskstat Read statistics from a remote endpoint Flags: -c, --conn string connection profile to use. -n, --devicename string name of target BLE device; overrides profile setting -h, --help help for newtmgr -l, --loglevel string log level to use (default \"info\") -t, --timeout float timeout in seconds (partial seconds allowed) (defaul t 10) -r, --tries int total number of tries in case of timeout (default 1) Use \"newtmgr [command] --help\" for more information about a command.","title":"Install Newtmgr On Windows"},{"location":"newtmgr/install_windows/#installing-newtmgr-on-windows","text":"You can build and install the newtmgr tool from the latest source on the master branch. Newtmgr is a Go (golang) package. This guide shows you how to install the tool from source. It assumes that you already installed the newt tool on Windows and have the Windows development environment and Go workspace set up.","title":"Installing Newtmgr on Windows"},{"location":"newtmgr/install_windows/#downloading-and-installing-the-newtmgr-tool","text":"The newtmgr Go package is mynewt.apache.org/newtmgr/newtmgr . It is stored in the Apache Mynewt newtmgr tool repository mirrored on github . Run the go get command, from your Go workspace, to download, build, and install the newtmgr tool: $cd $GOPATH $go get mynewt.apache.org/newtmgr/newtmgr $cd $GOPATH/src/mynewt.apache.org/newtmgr $ls DISCLAIMER NOTICE newtmgr LICENSE README.md nmxact $git status On branch master Your branch is up-to-date with 'origin/master'. nothing to commit, working directory clean Check that the newtmgr binary is installed and you are using the one from $GOPATH/bin : $ls $GOPATH/bin/newtmgr ~/dev/go/bin/newtmgr $which newtmgr ~/dev/go/bin/newtmgr Get information about the newtmgr tool: $newtmgr Newtmgr helps you manage remote devices running the Mynewt OS Usage: newtmgr [flags] newtmgr [command] Available Commands: config Read or write config value on target conn Manage newtmgr connection profiles crash Send crash command to remote endpoint using newtmgr datetime Manage datetime on the device echo Send data to remote endpoint using newtmgr, and receive data back fs Access files on device help Help about any command image Manage images on remote instance log Handles log on remote instance mpstat Read mempool statistics from a remote endpoint reset Performs a soft reset of target device run Run procedures on remote device stat Read statistics from a remote endpoint taskstat Read statistics from a remote endpoint Flags: -c, --conn string connection profile to use. -n, --devicename string name of target BLE device; overrides profile setting -h, --help help for newtmgr -l, --loglevel string log level to use (default \"info\") -t, --timeout float timeout in seconds (partial seconds allowed) (defaul t 10) -r, --tries int total number of tries in case of timeout (default 1) Use \"newtmgr [command] --help\" for more information about a command.","title":"Downloading and Installing the Newtmgr Tool"},{"location":"newtmgr/overview/","text":"Newt Manager Newt Manager (newtmgr) is the application tool that enables a user to communicate with and manage remote devices running the Mynewt OS. It uses a connection profile to establish a connection with a device and sends command requests to the device. The tool follows the same command structure as the newt tool . Available high-level commands The following are the high-level newtmgr commands. Some of these commands have subcommands. You can use the -h flag to get help for each command. See the documentation for each command in this guide if you need more information and examples. Available Commands: config Read or write a config value on a device conn Manage newtmgr connection profiles crash Send a crash command to a device datetime Manage datetime on a device echo Send data to a device and display the echoed back data fs Access files on a device image Manage images on a device log Manage logs on a device mpstats Read memory pool statistics from a device reset Send reset request to a device run Run test procedures on a device stat Read statistics from a device taskstats Read task statistics from a device Flags: -c, --conn string connection profile to use. -h, --help Help for newtmgr commands -l, --loglevel string log level to use (default \"info\") -t, --trace print all bytes transmitted and received","title":"toc"},{"location":"newtmgr/overview/#newt-manager","text":"Newt Manager (newtmgr) is the application tool that enables a user to communicate with and manage remote devices running the Mynewt OS. It uses a connection profile to establish a connection with a device and sends command requests to the device. The tool follows the same command structure as the newt tool .","title":"Newt Manager"},{"location":"newtmgr/overview/#available-high-level-commands","text":"The following are the high-level newtmgr commands. Some of these commands have subcommands. You can use the -h flag to get help for each command. See the documentation for each command in this guide if you need more information and examples. Available Commands: config Read or write a config value on a device conn Manage newtmgr connection profiles crash Send a crash command to a device datetime Manage datetime on a device echo Send data to a device and display the echoed back data fs Access files on a device image Manage images on a device log Manage logs on a device mpstats Read memory pool statistics from a device reset Send reset request to a device run Run test procedures on a device stat Read statistics from a device taskstats Read task statistics from a device Flags: -c, --conn string connection profile to use. -h, --help Help for newtmgr commands -l, --loglevel string log level to use (default \"info\") -t, --trace print all bytes transmitted and received","title":"Available high-level commands"},{"location":"newtmgr/protocol/","text":"Newt Manager Protocol Description How it works","title":"Protocol"},{"location":"newtmgr/protocol/#newt-manager-protocol","text":"","title":"Newt Manager Protocol"},{"location":"newtmgr/protocol/#description","text":"","title":"Description"},{"location":"newtmgr/protocol/#how-it-works","text":"","title":"How it works"},{"location":"newtmgr/command_list/newtmgr_config/","text":"newtmgr config Read and write config values on a device. Usage: newtmgr config <var-name> [var-value] -c <conn_profile> [flags] Global Flags: -c, --conn string connection profile to use. -h, --help Help for newtmgr commands -l, --loglevel string log level to use (default \"info\") -t, --trace print all bytes transmitted and received Description Reads and sets the value for the var-name config variable on a device. Specify a var-value to set the value for the var-name variable. Newtmgr uses the conn_profile connection profile to connect to the device. Examples Sub-command Usage Explanation newtmgr config myvar -c profile01 Reads the myvar config variable value from a device. Newtmgr connects to the device over a connection specified in the profile01 connection profile. newtmgr config myvar 2 -c profile01 Sets the myvar config variable to the value 2 on a device. Newtmgr connects to the device over a connection specified in the profile01 connection profile.","title":"newtmgr config"},{"location":"newtmgr/command_list/newtmgr_config/#newtmgr-config","text":"Read and write config values on a device.","title":"newtmgr config "},{"location":"newtmgr/command_list/newtmgr_config/#usage","text":"newtmgr config <var-name> [var-value] -c <conn_profile> [flags]","title":"Usage:"},{"location":"newtmgr/command_list/newtmgr_config/#global-flags","text":"-c, --conn string connection profile to use. -h, --help Help for newtmgr commands -l, --loglevel string log level to use (default \"info\") -t, --trace print all bytes transmitted and received","title":"Global Flags:"},{"location":"newtmgr/command_list/newtmgr_config/#description","text":"Reads and sets the value for the var-name config variable on a device. Specify a var-value to set the value for the var-name variable. Newtmgr uses the conn_profile connection profile to connect to the device.","title":"Description"},{"location":"newtmgr/command_list/newtmgr_config/#examples","text":"Sub-command Usage Explanation newtmgr config myvar -c profile01 Reads the myvar config variable value from a device. Newtmgr connects to the device over a connection specified in the profile01 connection profile. newtmgr config myvar 2 -c profile01 Sets the myvar config variable to the value 2 on a device. Newtmgr connects to the device over a connection specified in the profile01 connection profile.","title":"Examples"},{"location":"newtmgr/command_list/newtmgr_conn/","text":"newtmgr conn Manage newtmgr connection profiles. Usage: newtmgr conn [command] [flags] Global Flags: -c, --conn string connection profile to use. -h, --help Help for newtmgr commands -l, --loglevel string log level to use (default \"info\") -t, --trace print all bytes transmitted and received Description The conn command provides subcommands to add, delete, and view configuration profiles. Sub-command Explanation add The newtmgr conn add <conn_profile> <var-name=var-value...> command creates a connection profile named conn_profile . A profile consists of these variables: name : Connection name. Defaults to conn_profile when the variable is not set in the command. type : Connection type. Valid types are: serial , oic_serial , ble , oic_ble , udp , oic_udp . connstring : The physical or virtual port to use for the connection. addrtype : Device address type. Use with type ble . addr : Device address. Use with type ble . delete The newtmgr conn delete <conn_profile> command deletes the conn_profile connection profile. show The newtmgr conn show [conn_profile] command shows the information for the conn_profile connection profile. It shows information for all the connection profiles if conn_profile is not specified. Examples Sub-command Usage Explanation add newtmgr conn add myserial02 type=serial connstring=/dev/ttys002 Creates a connection profile for the serial port /dev/ttys002 and names it myserial02 delete newtmgr conn delete myserial02 Deletes the connection profile named myserial02 show newtmgr conn show myserial01 Displays the information for the myserial01 connection profile. show newtmgr conn show Displays the information for all connection profiles.","title":"newtmgr conn"},{"location":"newtmgr/command_list/newtmgr_conn/#newtmgr-conn","text":"Manage newtmgr connection profiles.","title":"newtmgr conn "},{"location":"newtmgr/command_list/newtmgr_conn/#usage","text":"newtmgr conn [command] [flags]","title":"Usage:"},{"location":"newtmgr/command_list/newtmgr_conn/#global-flags","text":"-c, --conn string connection profile to use. -h, --help Help for newtmgr commands -l, --loglevel string log level to use (default \"info\") -t, --trace print all bytes transmitted and received","title":"Global Flags:"},{"location":"newtmgr/command_list/newtmgr_conn/#description","text":"The conn command provides subcommands to add, delete, and view configuration profiles. Sub-command Explanation add The newtmgr conn add <conn_profile> <var-name=var-value...> command creates a connection profile named conn_profile . A profile consists of these variables: name : Connection name. Defaults to conn_profile when the variable is not set in the command. type : Connection type. Valid types are: serial , oic_serial , ble , oic_ble , udp , oic_udp . connstring : The physical or virtual port to use for the connection. addrtype : Device address type. Use with type ble . addr : Device address. Use with type ble . delete The newtmgr conn delete <conn_profile> command deletes the conn_profile connection profile. show The newtmgr conn show [conn_profile] command shows the information for the conn_profile connection profile. It shows information for all the connection profiles if conn_profile is not specified.","title":"Description"},{"location":"newtmgr/command_list/newtmgr_conn/#examples","text":"Sub-command Usage Explanation add newtmgr conn add myserial02 type=serial connstring=/dev/ttys002 Creates a connection profile for the serial port /dev/ttys002 and names it myserial02 delete newtmgr conn delete myserial02 Deletes the connection profile named myserial02 show newtmgr conn show myserial01 Displays the information for the myserial01 connection profile. show newtmgr conn show Displays the information for all connection profiles.","title":"Examples"},{"location":"newtmgr/command_list/newtmgr_crash/","text":"newtmgr crash Send a crash command to a device. Usage: newtmgr crash <div0|jump0|ref0|assert|wdog> -c <conn_profile> [flags] Global Flags: -c, --conn string connection profile to use. -h, --help Help for newtmgr commands -l, --loglevel string log level to use (default \"info\") -t, --trace print all bytes transmitted and received Description Sends a crash command to a device to run one of the following crash tests: div0 , jump0 , ref0 , assert , wdog . Newtmgr uses the conn_profile connection profile to connect to the device. Examples Sub-command Usage Explanation newtmgr crash div0 -c profile01 Sends a request to a device to execute a divide by 0 test. Newtmgr connects to the device over a connection specified in the profile01 connection profile. newtmgr crash ref0 -c profile01 Sends a request to a device to execute a nil pointer reference test. Newtmgr connects to the device over a connection specified in the profile01 connection profile.","title":"newtmgr crash"},{"location":"newtmgr/command_list/newtmgr_crash/#newtmgr-crash","text":"Send a crash command to a device.","title":"newtmgr crash "},{"location":"newtmgr/command_list/newtmgr_crash/#usage","text":"newtmgr crash <div0|jump0|ref0|assert|wdog> -c <conn_profile> [flags]","title":"Usage:"},{"location":"newtmgr/command_list/newtmgr_crash/#global-flags","text":"-c, --conn string connection profile to use. -h, --help Help for newtmgr commands -l, --loglevel string log level to use (default \"info\") -t, --trace print all bytes transmitted and received","title":"Global Flags:"},{"location":"newtmgr/command_list/newtmgr_crash/#description","text":"Sends a crash command to a device to run one of the following crash tests: div0 , jump0 , ref0 , assert , wdog . Newtmgr uses the conn_profile connection profile to connect to the device.","title":"Description"},{"location":"newtmgr/command_list/newtmgr_crash/#examples","text":"Sub-command Usage Explanation newtmgr crash div0 -c profile01 Sends a request to a device to execute a divide by 0 test. Newtmgr connects to the device over a connection specified in the profile01 connection profile. newtmgr crash ref0 -c profile01 Sends a request to a device to execute a nil pointer reference test. Newtmgr connects to the device over a connection specified in the profile01 connection profile.","title":"Examples"},{"location":"newtmgr/command_list/newtmgr_datetime/","text":"newtmgr datetime Manage datetime on a device. Usage: newtmgr datetime [datetime-value] -c <conn_profile> [flags] Global Flags: -c, --conn string connection profile to use. -h, --help Help for newtmgr commands -l, --loglevel string log level to use (default \"info\") -t, --trace print all bytes transmitted and received Description Reads or sets the datetime on a device. Specify a datetime-value in the command to set the datetime on the device. Newtmgr uses the conn_profile connection profile to connect to the device. Note : You must specify the datetime-value in the RFC 3339 format. Examples Sub-command Usage Explanation newtmgr datetime -c profile01 Reads the datetime value from a device. Newtmgr connects to the device over a connection specified in the profile01 connection profile. newtmgr datetime 2017-03-01T22:44:00 -c profile01 Sets the datetime on a device to March 1st 2017 22:44:00 UTC. Newtmgr connects to the device over a connection specified in the profile01 connection profile. newtmgr datetime 2017-03-01T22:44:00-08:00 -c profile01 Sets the datetime on a device to March 1st 2017 22:44:00 PST. Newtmgr connects to the device over a connection specified in the profile01 connection profile.","title":"newtmgr datetime"},{"location":"newtmgr/command_list/newtmgr_datetime/#newtmgr-datetime","text":"Manage datetime on a device.","title":"newtmgr datetime "},{"location":"newtmgr/command_list/newtmgr_datetime/#usage","text":"newtmgr datetime [datetime-value] -c <conn_profile> [flags]","title":"Usage:"},{"location":"newtmgr/command_list/newtmgr_datetime/#global-flags","text":"-c, --conn string connection profile to use. -h, --help Help for newtmgr commands -l, --loglevel string log level to use (default \"info\") -t, --trace print all bytes transmitted and received","title":"Global Flags:"},{"location":"newtmgr/command_list/newtmgr_datetime/#description","text":"Reads or sets the datetime on a device. Specify a datetime-value in the command to set the datetime on the device. Newtmgr uses the conn_profile connection profile to connect to the device. Note : You must specify the datetime-value in the RFC 3339 format.","title":"Description"},{"location":"newtmgr/command_list/newtmgr_datetime/#examples","text":"Sub-command Usage Explanation newtmgr datetime -c profile01 Reads the datetime value from a device. Newtmgr connects to the device over a connection specified in the profile01 connection profile. newtmgr datetime 2017-03-01T22:44:00 -c profile01 Sets the datetime on a device to March 1st 2017 22:44:00 UTC. Newtmgr connects to the device over a connection specified in the profile01 connection profile. newtmgr datetime 2017-03-01T22:44:00-08:00 -c profile01 Sets the datetime on a device to March 1st 2017 22:44:00 PST. Newtmgr connects to the device over a connection specified in the profile01 connection profile.","title":"Examples"},{"location":"newtmgr/command_list/newtmgr_echo/","text":"newtmgr echo Send data to a device and display the echoed back data. Usage: newtmgr echo <text> -c <conn_profile> [flags] Global Flags: -c, --conn string connection profile to use -h, --help Help for newtmgr commands -l, --loglevel string log level to use (default \"info\") -t, --trace print all bytes transmitted and received Description Sends the text to a device and outputs the text response from the device. Newtmgr uses the conn_profile connection profile to connect to the device. Examples Sub-command Usage Explanation newtmgr echo hello -c profile01 Sends the text 'hello' to a device and displays the echoed back data. Newtmgr connects to the device over a connection specified in the profile01 profile.","title":"newtmgr echo"},{"location":"newtmgr/command_list/newtmgr_echo/#newtmgr-echo","text":"Send data to a device and display the echoed back data.","title":"newtmgr echo "},{"location":"newtmgr/command_list/newtmgr_echo/#usage","text":"newtmgr echo <text> -c <conn_profile> [flags]","title":"Usage:"},{"location":"newtmgr/command_list/newtmgr_echo/#global-flags","text":"-c, --conn string connection profile to use -h, --help Help for newtmgr commands -l, --loglevel string log level to use (default \"info\") -t, --trace print all bytes transmitted and received","title":"Global Flags:"},{"location":"newtmgr/command_list/newtmgr_echo/#description","text":"Sends the text to a device and outputs the text response from the device. Newtmgr uses the conn_profile connection profile to connect to the device.","title":"Description"},{"location":"newtmgr/command_list/newtmgr_echo/#examples","text":"Sub-command Usage Explanation newtmgr echo hello -c profile01 Sends the text 'hello' to a device and displays the echoed back data. Newtmgr connects to the device over a connection specified in the profile01 profile.","title":"Examples"},{"location":"newtmgr/command_list/newtmgr_fs/","text":"newtmgr fs Access files on a device. Usage: newtmgr fs [command] -c <conn_profile> [flags] Global Flags: -c, --conn string connection profile to use. -h, --help Help for newtmgr commands -l, --loglevel string log level to use (default \"info\") -t, --trace print all bytes transmitted and received Description The fs command provides the subcommands to download a file from and upload a file to a device. Newtmgr uses the conn_profile connection profile to connect to the device. Sub-command Explanation download The newtmgr download <src-filename> <dst-filename> command downloads the file named <src-filename> from a device and names it <dst-filename> on your host. upload The newtmgr upload <src-filename> <dst-filename> command uploads the file named <src-filename> to a device and names the file <dst-filename> on the device. Examples Sub-command Usage Explanation download newtmgr fs download /cfg/mfg mfg.txt -c profile01 Downloads the file name /cfg/mfg from a device and names the file mfg.txt on your host. Newtmgr connects to the device over a connection specified in the profile01 connection profile. upload newtmgr fs upload mymfg.txt /cfg/mfg -c profile01 Uploads the file name mymfg.txt to a device and names the file cfg/mfg on the device. Newtmgr connects to the device over a connection specified in the profile01 connection profile.","title":"newtmgr fs"},{"location":"newtmgr/command_list/newtmgr_fs/#newtmgr-fs","text":"Access files on a device.","title":"newtmgr fs"},{"location":"newtmgr/command_list/newtmgr_fs/#usage","text":"newtmgr fs [command] -c <conn_profile> [flags]","title":"Usage:"},{"location":"newtmgr/command_list/newtmgr_fs/#global-flags","text":"-c, --conn string connection profile to use. -h, --help Help for newtmgr commands -l, --loglevel string log level to use (default \"info\") -t, --trace print all bytes transmitted and received","title":"Global Flags:"},{"location":"newtmgr/command_list/newtmgr_fs/#description","text":"The fs command provides the subcommands to download a file from and upload a file to a device. Newtmgr uses the conn_profile connection profile to connect to the device. Sub-command Explanation download The newtmgr download <src-filename> <dst-filename> command downloads the file named <src-filename> from a device and names it <dst-filename> on your host. upload The newtmgr upload <src-filename> <dst-filename> command uploads the file named <src-filename> to a device and names the file <dst-filename> on the device.","title":"Description"},{"location":"newtmgr/command_list/newtmgr_fs/#examples","text":"Sub-command Usage Explanation download newtmgr fs download /cfg/mfg mfg.txt -c profile01 Downloads the file name /cfg/mfg from a device and names the file mfg.txt on your host. Newtmgr connects to the device over a connection specified in the profile01 connection profile. upload newtmgr fs upload mymfg.txt /cfg/mfg -c profile01 Uploads the file name mymfg.txt to a device and names the file cfg/mfg on the device. Newtmgr connects to the device over a connection specified in the profile01 connection profile.","title":"Examples"},{"location":"newtmgr/command_list/newtmgr_image/","text":"newtmgr image Manage images on a device. Usage: newtmgr image [command] -c <connection_profile> [flags] Flags: The coredownload subcommand uses the following local flags: -n, --bytes uint32 Number of bytes of the core to download -e, --elfify Create an ELF file --offset unint32 Offset of the core file to start the download Global Flags: -c, --conn string connection profile to use -h, --help Help for newtmgr commands -l, --loglevel string log level to use (default \"info\") -t, --trace print all bytes transmitted and received Description The image command provides subcommands to manage core and image files on a device. Newtmgr uses the conn_profile connection profile to connect to the device. Sub-command Explanation confirm The newtmgr image confirm [hex-image-hash] command makes an image setup permanent on a device. If a hex-image-hash hash value is specified, Mynewt permanently switches to the image identified by the hash value. If a hash value is not specified, the current image is made permanent. coreconvert The newtmgr image coreconvert <core-filename> <elf-file> command converts the core-filename core file to an ELF format and names it elf-file . Note : This command does not download the core file from a device. The core file must exist on your host. coredownload The newtmgr image coredownload <core-filename> command downloads the core file from a device and names the file core-filename on your host. Use the local flags under Flags to customize the command. coreerase The newtmgr image coreerase command erases the core file on a device. corelist The newtmgr image corelist command lists the core(s) on a device. list The newtmgr image list command displays information for the images on a device. test The newtmgr test <hex-image-hash> command tests the image, identified by the hex-image-hash hash value, on next reboot. upload The newtmgr image upload <image-file> command uploads the image-file image file to a device. Examples Sub-command Usage Explanation confirm newtmgr confirm -c profile01 Makes the current image setup on a device permanent. Newtmgr connects to the device over a connection specified in the profile01 connection profile. confirm newtmgr confirm be9699809a049...73d77f -c profile01 Makes the image, identified by the be9699809a049...73d77f hash value, setup on a device permanent. Newtmgr connects to the device over a connection specified in the profile01 connection profile. coreconvert newtmgr image coreconvert mycore mycore.elf Converts the mycore file to the ELF format and saves it in the mycore.elf file. coredownload newtmgr image coredownload mycore -c profile01 Downloads the core from a device and saves it in the mycore file. Newtmgr connects to the device over a connection specified in the profile01 connection profile. coredownload newtmgr image coredownload mycore -e -c profile01 Downloads the core from a device, converts the core file into the ELF format, and saves it in the mycore file. Newtmgr connects to the device over a connection specified in the profile01 connection profile. coredownload newtmgr image coredownload mycore --offset 10 -n 30 -c profile01 Downloads 30 bytes, starting at offset 10, of the core from a device and saves it in the mycore file. Newtmgr connects to the device over a connection specified in the profile01 connection profile. coreerase newtmgr image coreerase -c profile01 Erases the core file on a device. Newtmgr connects to the device over a connection specified in the profile01 connection profile. corelist newtmgr image corelist -c profile01 Lists the core files on a device. Newtmgr connects to the device over a connection specified in the profile01 connection profile. list newtmgr image list -c profile01 Lists the images on a device. Newtmgr connects to the device over a connection specified in the profile01 connection profile. test newtmgr image test be9699809a049...73d77f Tests the image, identified by the be9699809a049...73d77f hash value, during the next reboot on a device. Newtmgr connects to the device over a connection specified in the profile01 connection profile. upload newtmgr image upload bletiny.img -c profile01 Uploads the bletiny.img image to a device. Newtmgr connects to the device over a connection specified in the profile01 connection profile.","title":"newtmgr image"},{"location":"newtmgr/command_list/newtmgr_image/#newtmgr-image","text":"Manage images on a device.","title":"newtmgr image "},{"location":"newtmgr/command_list/newtmgr_image/#usage","text":"newtmgr image [command] -c <connection_profile> [flags]","title":"Usage:"},{"location":"newtmgr/command_list/newtmgr_image/#flags","text":"The coredownload subcommand uses the following local flags: -n, --bytes uint32 Number of bytes of the core to download -e, --elfify Create an ELF file --offset unint32 Offset of the core file to start the download","title":"Flags:"},{"location":"newtmgr/command_list/newtmgr_image/#global-flags","text":"-c, --conn string connection profile to use -h, --help Help for newtmgr commands -l, --loglevel string log level to use (default \"info\") -t, --trace print all bytes transmitted and received","title":"Global Flags:"},{"location":"newtmgr/command_list/newtmgr_image/#description","text":"The image command provides subcommands to manage core and image files on a device. Newtmgr uses the conn_profile connection profile to connect to the device. Sub-command Explanation confirm The newtmgr image confirm [hex-image-hash] command makes an image setup permanent on a device. If a hex-image-hash hash value is specified, Mynewt permanently switches to the image identified by the hash value. If a hash value is not specified, the current image is made permanent. coreconvert The newtmgr image coreconvert <core-filename> <elf-file> command converts the core-filename core file to an ELF format and names it elf-file . Note : This command does not download the core file from a device. The core file must exist on your host. coredownload The newtmgr image coredownload <core-filename> command downloads the core file from a device and names the file core-filename on your host. Use the local flags under Flags to customize the command. coreerase The newtmgr image coreerase command erases the core file on a device. corelist The newtmgr image corelist command lists the core(s) on a device. list The newtmgr image list command displays information for the images on a device. test The newtmgr test <hex-image-hash> command tests the image, identified by the hex-image-hash hash value, on next reboot. upload The newtmgr image upload <image-file> command uploads the image-file image file to a device.","title":"Description"},{"location":"newtmgr/command_list/newtmgr_image/#examples","text":"Sub-command Usage Explanation confirm newtmgr confirm -c profile01 Makes the current image setup on a device permanent. Newtmgr connects to the device over a connection specified in the profile01 connection profile. confirm newtmgr confirm be9699809a049...73d77f -c profile01 Makes the image, identified by the be9699809a049...73d77f hash value, setup on a device permanent. Newtmgr connects to the device over a connection specified in the profile01 connection profile. coreconvert newtmgr image coreconvert mycore mycore.elf Converts the mycore file to the ELF format and saves it in the mycore.elf file. coredownload newtmgr image coredownload mycore -c profile01 Downloads the core from a device and saves it in the mycore file. Newtmgr connects to the device over a connection specified in the profile01 connection profile. coredownload newtmgr image coredownload mycore -e -c profile01 Downloads the core from a device, converts the core file into the ELF format, and saves it in the mycore file. Newtmgr connects to the device over a connection specified in the profile01 connection profile. coredownload newtmgr image coredownload mycore --offset 10 -n 30 -c profile01 Downloads 30 bytes, starting at offset 10, of the core from a device and saves it in the mycore file. Newtmgr connects to the device over a connection specified in the profile01 connection profile. coreerase newtmgr image coreerase -c profile01 Erases the core file on a device. Newtmgr connects to the device over a connection specified in the profile01 connection profile. corelist newtmgr image corelist -c profile01 Lists the core files on a device. Newtmgr connects to the device over a connection specified in the profile01 connection profile. list newtmgr image list -c profile01 Lists the images on a device. Newtmgr connects to the device over a connection specified in the profile01 connection profile. test newtmgr image test be9699809a049...73d77f Tests the image, identified by the be9699809a049...73d77f hash value, during the next reboot on a device. Newtmgr connects to the device over a connection specified in the profile01 connection profile. upload newtmgr image upload bletiny.img -c profile01 Uploads the bletiny.img image to a device. Newtmgr connects to the device over a connection specified in the profile01 connection profile.","title":"Examples"},{"location":"newtmgr/command_list/newtmgr_logs/","text":"newtmgr log Manage logs on a device. Usage: newtmgr log [command] [flags] Global Flags: -c, --conn string connection profile to use. -h, --help Help for newtmgr commands -l, --loglevel string log level to use (default \"info\") -t, --trace print all bytes transmitted and received Description The log command provides subcommands to manage logs on a device. Newtmgr uses the conn_profile connection profile to connect to the device. Sub-command Explanation clear The newtmgr log clear command clears the logs on a device. level_list The newtmgr level_list command shows the log levels on a device. list The newtmgr log list command shows the log names on a device. module_list The newtmgr log module_list command shows the log module names on a device. show The newtmgr log show command shows the logs on a device. Examples Sub-command Usage Explanation clear newtmgr log clear -c profile01 Clears the logs on a device. Newtmgr connects to the device over a connection specified in the profile01 connection profile. level_list newtmgr log level_list -c profile01 Shows the log levels on a device. Newtmgr connects to the device over a connection specified in the profile01 connection profile. list newtmgr log list -c profile01 Shows the log names on a device. Newtmgr connects to the device over a connection specified in the profile01 connection profile. module_list newtmgr log module_list -c profile01 Shows the log module names on a device. Newtmgr connects to the device over a connection specified in the profile01 connection profile. show newtmgr log show -c profile01 Shows the logs on a device. Newtmgr connects to the device over a connection specified in the profile01 connection profile.","title":"newtmgr log"},{"location":"newtmgr/command_list/newtmgr_logs/#newtmgr-log","text":"Manage logs on a device.","title":"newtmgr log "},{"location":"newtmgr/command_list/newtmgr_logs/#usage","text":"newtmgr log [command] [flags]","title":"Usage:"},{"location":"newtmgr/command_list/newtmgr_logs/#global-flags","text":"-c, --conn string connection profile to use. -h, --help Help for newtmgr commands -l, --loglevel string log level to use (default \"info\") -t, --trace print all bytes transmitted and received","title":"Global Flags:"},{"location":"newtmgr/command_list/newtmgr_logs/#description","text":"The log command provides subcommands to manage logs on a device. Newtmgr uses the conn_profile connection profile to connect to the device. Sub-command Explanation clear The newtmgr log clear command clears the logs on a device. level_list The newtmgr level_list command shows the log levels on a device. list The newtmgr log list command shows the log names on a device. module_list The newtmgr log module_list command shows the log module names on a device. show The newtmgr log show command shows the logs on a device.","title":"Description"},{"location":"newtmgr/command_list/newtmgr_logs/#examples","text":"Sub-command Usage Explanation clear newtmgr log clear -c profile01 Clears the logs on a device. Newtmgr connects to the device over a connection specified in the profile01 connection profile. level_list newtmgr log level_list -c profile01 Shows the log levels on a device. Newtmgr connects to the device over a connection specified in the profile01 connection profile. list newtmgr log list -c profile01 Shows the log names on a device. Newtmgr connects to the device over a connection specified in the profile01 connection profile. module_list newtmgr log module_list -c profile01 Shows the log module names on a device. Newtmgr connects to the device over a connection specified in the profile01 connection profile. show newtmgr log show -c profile01 Shows the logs on a device. Newtmgr connects to the device over a connection specified in the profile01 connection profile.","title":"Examples"},{"location":"newtmgr/command_list/newtmgr_mpstats/","text":"newtmgr mpstats Read memory pool statistics from a device. Usage: newtmgr mpstats -c <conn_profile> [flags] Global Flags: -c, --conn string connection profile to use. -h, --help Help for newtmgr commands -l, --loglevel string log level to use (default \"info\") -t, --trace print all bytes transmitted and received Description Reads and displays the memory pool statistics from a device. Newtmgr uses the conn_profile connection profile to connect to the device. It lists the following statistics for each memory pool: name : Memory pool name blksz : Size (number of bytes) of each memory block cnt : Number of blocks allocated for the pool free : Number of free blocks min : The lowest number of free blocks that were available Examples Sub-command Usage Explanation newtmgr mpstats -c profile01 Reads and displays the memory pool statistics from a device. Newtmgr connects to the device over a connection specified in the profile01 connection profile. Here is an example output for the myble application from the Enabling Newt Manager in any app tutiorial: newtmgr mpstats -c myserial Return Code = 0 name blksz cnt free min ble_l2cap_sig_proc_pool 20 1 1 1 ble_att_svr_prep_entry_pool 12 64 64 64 ble_hci_ram_evt_hi_pool 72 2 2 1 ble_hs_hci_ev_pool 16 10 10 9 ble_att_svr_entry_pool 20 75 0 0 ble_gattc_proc_pool 56 4 4 4 bletiny_dsc_pool 28 64 64 64 ble_hs_conn_pool 84 1 1 1 ble_gap_update 24 1 1 1 bletiny_svc_pool 32 32 32 32 ble_gatts_clt_cfg_pool 12 2 1 1 msys_1 292 12 9 6 ble_hci_ram_evt_lo_pool 72 8 8 8 ble_l2cap_chan_pool 24 3 3 3 bletiny_chr_pool 36 64 64 64","title":"newtmgr mpstats"},{"location":"newtmgr/command_list/newtmgr_mpstats/#newtmgr-mpstats","text":"Read memory pool statistics from a device.","title":"newtmgr mpstats "},{"location":"newtmgr/command_list/newtmgr_mpstats/#usage","text":"newtmgr mpstats -c <conn_profile> [flags]","title":"Usage:"},{"location":"newtmgr/command_list/newtmgr_mpstats/#global-flags","text":"-c, --conn string connection profile to use. -h, --help Help for newtmgr commands -l, --loglevel string log level to use (default \"info\") -t, --trace print all bytes transmitted and received","title":"Global Flags:"},{"location":"newtmgr/command_list/newtmgr_mpstats/#description","text":"Reads and displays the memory pool statistics from a device. Newtmgr uses the conn_profile connection profile to connect to the device. It lists the following statistics for each memory pool: name : Memory pool name blksz : Size (number of bytes) of each memory block cnt : Number of blocks allocated for the pool free : Number of free blocks min : The lowest number of free blocks that were available","title":"Description"},{"location":"newtmgr/command_list/newtmgr_mpstats/#examples","text":"Sub-command Usage Explanation newtmgr mpstats -c profile01 Reads and displays the memory pool statistics from a device. Newtmgr connects to the device over a connection specified in the profile01 connection profile. Here is an example output for the myble application from the Enabling Newt Manager in any app tutiorial: newtmgr mpstats -c myserial Return Code = 0 name blksz cnt free min ble_l2cap_sig_proc_pool 20 1 1 1 ble_att_svr_prep_entry_pool 12 64 64 64 ble_hci_ram_evt_hi_pool 72 2 2 1 ble_hs_hci_ev_pool 16 10 10 9 ble_att_svr_entry_pool 20 75 0 0 ble_gattc_proc_pool 56 4 4 4 bletiny_dsc_pool 28 64 64 64 ble_hs_conn_pool 84 1 1 1 ble_gap_update 24 1 1 1 bletiny_svc_pool 32 32 32 32 ble_gatts_clt_cfg_pool 12 2 1 1 msys_1 292 12 9 6 ble_hci_ram_evt_lo_pool 72 8 8 8 ble_l2cap_chan_pool 24 3 3 3 bletiny_chr_pool 36 64 64 64","title":"Examples"},{"location":"newtmgr/command_list/newtmgr_reset/","text":"newtmgr reset Send a reset request to a device. Usage: newtmgr reset <conn_profile> [flags] Global Flags: -c, --conn string connection profile to use. -h, --help Help for newtmgr commands -l, --loglevel string log level to use (default \"info\") -t, --trace print all bytes transmitted and received Description Resets a device. Newtmgr uses the conn_profile connection profile to connect to the device. Examples Sub-command Usage Explanation newtmgr reset -c profile01 Resets a device. Newtmgr connects to the device over a connection specified in the profile01 connection profile.","title":"newtmgr reset"},{"location":"newtmgr/command_list/newtmgr_reset/#newtmgr-reset","text":"Send a reset request to a device.","title":"newtmgr reset "},{"location":"newtmgr/command_list/newtmgr_reset/#usage","text":"newtmgr reset <conn_profile> [flags]","title":"Usage:"},{"location":"newtmgr/command_list/newtmgr_reset/#global-flags","text":"-c, --conn string connection profile to use. -h, --help Help for newtmgr commands -l, --loglevel string log level to use (default \"info\") -t, --trace print all bytes transmitted and received","title":"Global Flags:"},{"location":"newtmgr/command_list/newtmgr_reset/#description","text":"Resets a device. Newtmgr uses the conn_profile connection profile to connect to the device.","title":"Description"},{"location":"newtmgr/command_list/newtmgr_reset/#examples","text":"Sub-command Usage Explanation newtmgr reset -c profile01 Resets a device. Newtmgr connects to the device over a connection specified in the profile01 connection profile.","title":"Examples"},{"location":"newtmgr/command_list/newtmgr_run/","text":"newtmgr run Run test procedures on a device. Usage: newtmgr run [command] -c <conn_profile> [flags] Global Flags: -c, --conn string connection profile to use. -h, --help Help for newtmgr commands -l, --loglevel string log level to use (default \"info\") -t, --trace print all bytes transmitted and received Description The run command provides subcommands to run test procedures on a device. Newtmgr uses the conn_profile connection profile to connect to the device. Sub-command Explanation list The newtmgr run list command lists the registered tests on a device. test The newtmgr run test [all|testname] [token-value] command runs the testname test or all tests on a device. All tests are run if all or no testname is specified. If a token-value is specified, the token value is output with the log messages. Examples Sub-command Usage Explanation list newtmgr run list -c profile01 Lists all the registered tests on a device. Newtmgr connects to the device over a connection specified in the profile01 connection profile. test newtmgr run test all 201612161220 -c profile01 Runs all the tests on a device. Outputs the 201612161220 token with the log messages. Newtmgr connects to the device over a connection specified in the profile01 connection profile. test newtmgr run test mynewtsanity -c profile01 Runs the mynewtsanity test on a device. Newtmgr connects to the device over a connection specified in the profile01 connection profile.","title":"newtmgr run"},{"location":"newtmgr/command_list/newtmgr_run/#newtmgr-run","text":"Run test procedures on a device.","title":"newtmgr run "},{"location":"newtmgr/command_list/newtmgr_run/#usage","text":"newtmgr run [command] -c <conn_profile> [flags]","title":"Usage:"},{"location":"newtmgr/command_list/newtmgr_run/#global-flags","text":"-c, --conn string connection profile to use. -h, --help Help for newtmgr commands -l, --loglevel string log level to use (default \"info\") -t, --trace print all bytes transmitted and received","title":"Global Flags:"},{"location":"newtmgr/command_list/newtmgr_run/#description","text":"The run command provides subcommands to run test procedures on a device. Newtmgr uses the conn_profile connection profile to connect to the device. Sub-command Explanation list The newtmgr run list command lists the registered tests on a device. test The newtmgr run test [all|testname] [token-value] command runs the testname test or all tests on a device. All tests are run if all or no testname is specified. If a token-value is specified, the token value is output with the log messages.","title":"Description"},{"location":"newtmgr/command_list/newtmgr_run/#examples","text":"Sub-command Usage Explanation list newtmgr run list -c profile01 Lists all the registered tests on a device. Newtmgr connects to the device over a connection specified in the profile01 connection profile. test newtmgr run test all 201612161220 -c profile01 Runs all the tests on a device. Outputs the 201612161220 token with the log messages. Newtmgr connects to the device over a connection specified in the profile01 connection profile. test newtmgr run test mynewtsanity -c profile01 Runs the mynewtsanity test on a device. Newtmgr connects to the device over a connection specified in the profile01 connection profile.","title":"Examples"},{"location":"newtmgr/command_list/newtmgr_stat/","text":"newtmgr stat Read statistics from a device. Usage: newtmgr stat [stats_name] -c <conn_profile> [flags] newtmgr stat [command] -c <conn_profile> [flags] Global Flags: -c, --conn string connection profile to use. -h, --help Help for newtmgr commands -l, --loglevel string log level to use (default \"info\") -t, --trace print all bytes transmitted and received Description Displays statistic for the Stats named stats_name from a device. You can use the list subcommand to get a list of the Stats names from the device. Newtmgr uses the conn_profile connection profile to connect to the device. Sub-command Explanation The newtmgr stat [stats_name] command displays the statistics for the stats_name Stats from a device. It displays the list of Stats names if a stats_name value is not specified. list The newtmgr stat list command displays the list of Stats names from a device. Examples Sub-command Usage Explanation newtmgr stat ble_att -c profile01 Displays the ble_att statistics on a device. Newtmgr connects to the device over a connection specified in the profile01 connection profile. newtmgr stat -c profile01 Displays the list of Stats names from a device. Newtmgr connects to the device over a connection specified in the profile01 connection profile. list newtmgr stat list -c profile01 Displays the list of Stats names from a device. Newtmgr connects to the device over a connection specified in the profile01 connection profile. Here are some example outputs for the myble application from the Enabling Newt Manager in any app tutiorial: The statistics for the ble_att Stats: $ newtmgr stat ble_att -c myserial Return Code = 0 Stats Name: ble_att read_type_req_rx: 0 read_rsp_rx: 0 read_group_type_rsp_tx: 0 prep_write_rsp_tx: 0 find_type_value_req_tx: 0 read_type_rsp_rx: 0 read_mult_req_rx: 0 notify_req_tx: 0 indicate_req_tx: 0 ... write_cmd_rx: 0 prep_write_rsp_rx: 0 read_type_rsp_tx: 0 read_req_tx: 0 read_mult_req_tx: 0 read_group_type_req_rx: 0 write_rsp_tx: 0 exec_write_rsp_rx: 0 The list of Stats names: $ newtmgr stat -c myserial [stat ble_l2cap ble_att ble_gap ble_gattc ble_gatts ble_hs ble_ll_conn ble_ll ble_phy] Return Code = 0 The list of Stats names using the list subcommand: $ newtmgr stat list -c myserial [stat ble_l2cap ble_att ble_gap ble_gattc ble_gatts ble_hs ble_ll_conn ble_ll ble_phy] Return Code = 0","title":"newtmgr stat"},{"location":"newtmgr/command_list/newtmgr_stat/#newtmgr-stat","text":"Read statistics from a device.","title":"newtmgr stat"},{"location":"newtmgr/command_list/newtmgr_stat/#usage","text":"newtmgr stat [stats_name] -c <conn_profile> [flags] newtmgr stat [command] -c <conn_profile> [flags]","title":"Usage:"},{"location":"newtmgr/command_list/newtmgr_stat/#global-flags","text":"-c, --conn string connection profile to use. -h, --help Help for newtmgr commands -l, --loglevel string log level to use (default \"info\") -t, --trace print all bytes transmitted and received","title":"Global Flags:"},{"location":"newtmgr/command_list/newtmgr_stat/#description","text":"Displays statistic for the Stats named stats_name from a device. You can use the list subcommand to get a list of the Stats names from the device. Newtmgr uses the conn_profile connection profile to connect to the device. Sub-command Explanation The newtmgr stat [stats_name] command displays the statistics for the stats_name Stats from a device. It displays the list of Stats names if a stats_name value is not specified. list The newtmgr stat list command displays the list of Stats names from a device.","title":"Description"},{"location":"newtmgr/command_list/newtmgr_stat/#examples","text":"Sub-command Usage Explanation newtmgr stat ble_att -c profile01 Displays the ble_att statistics on a device. Newtmgr connects to the device over a connection specified in the profile01 connection profile. newtmgr stat -c profile01 Displays the list of Stats names from a device. Newtmgr connects to the device over a connection specified in the profile01 connection profile. list newtmgr stat list -c profile01 Displays the list of Stats names from a device. Newtmgr connects to the device over a connection specified in the profile01 connection profile. Here are some example outputs for the myble application from the Enabling Newt Manager in any app tutiorial: The statistics for the ble_att Stats: $ newtmgr stat ble_att -c myserial Return Code = 0 Stats Name: ble_att read_type_req_rx: 0 read_rsp_rx: 0 read_group_type_rsp_tx: 0 prep_write_rsp_tx: 0 find_type_value_req_tx: 0 read_type_rsp_rx: 0 read_mult_req_rx: 0 notify_req_tx: 0 indicate_req_tx: 0 ... write_cmd_rx: 0 prep_write_rsp_rx: 0 read_type_rsp_tx: 0 read_req_tx: 0 read_mult_req_tx: 0 read_group_type_req_rx: 0 write_rsp_tx: 0 exec_write_rsp_rx: 0 The list of Stats names: $ newtmgr stat -c myserial [stat ble_l2cap ble_att ble_gap ble_gattc ble_gatts ble_hs ble_ll_conn ble_ll ble_phy] Return Code = 0 The list of Stats names using the list subcommand: $ newtmgr stat list -c myserial [stat ble_l2cap ble_att ble_gap ble_gattc ble_gatts ble_hs ble_ll_conn ble_ll ble_phy] Return Code = 0","title":"Examples"},{"location":"newtmgr/command_list/newtmgr_taskstats/","text":"newtmgr taskstats Read task statistics from a device. Usage: newtmgr taskstats -c <conn_profile> [flags] Global Flags: -c, --conn string connection profile to use. -h, --help Help for newtmgr commands -l, --loglevel string log level to use (default \"info\") -t, --trace print all bytes transmitted and received Description Reads and displays the task statistics from a device. Newtmgr uses the conn_profile connection profile to connect to the device. It lists the following statistics for each task: task : Task name pri : Task priority runtime : The time (ms) that the task has been running for csw : Number of times the task has switched context stksz : Stack size allocated for the task stkuse : Actual stack size the task uses last_checkin : Last sanity checkin with the Sanity Task next_checkin : Next sanity checkin Examples Sub-command Usage Explanation newtmgr taskstats -c profile0 Reads and displays the task statistics from a device. Newtmgr connects to the device over a connection specified in the profile01 connection profile. Here is an example output for the myble application from the Enabling Newt Manager in any app tutiorial: newtmgr taskstats -c myserial Return Code = 0 task pri tid runtime csw stksz stkuse last_checkin next_checkin idle 255 0 151917 47 64 34 0 0 main 127 1 2 59 512 188 0 0 ble_ll 0 2 0 14 80 56 0 0","title":"newtmgr taskstats"},{"location":"newtmgr/command_list/newtmgr_taskstats/#newtmgr-taskstats","text":"Read task statistics from a device.","title":"newtmgr taskstats "},{"location":"newtmgr/command_list/newtmgr_taskstats/#usage","text":"newtmgr taskstats -c <conn_profile> [flags]","title":"Usage:"},{"location":"newtmgr/command_list/newtmgr_taskstats/#global-flags","text":"-c, --conn string connection profile to use. -h, --help Help for newtmgr commands -l, --loglevel string log level to use (default \"info\") -t, --trace print all bytes transmitted and received","title":"Global Flags:"},{"location":"newtmgr/command_list/newtmgr_taskstats/#description","text":"Reads and displays the task statistics from a device. Newtmgr uses the conn_profile connection profile to connect to the device. It lists the following statistics for each task: task : Task name pri : Task priority runtime : The time (ms) that the task has been running for csw : Number of times the task has switched context stksz : Stack size allocated for the task stkuse : Actual stack size the task uses last_checkin : Last sanity checkin with the Sanity Task next_checkin : Next sanity checkin","title":"Description"},{"location":"newtmgr/command_list/newtmgr_taskstats/#examples","text":"Sub-command Usage Explanation newtmgr taskstats -c profile0 Reads and displays the task statistics from a device. Newtmgr connects to the device over a connection specified in the profile01 connection profile. Here is an example output for the myble application from the Enabling Newt Manager in any app tutiorial: newtmgr taskstats -c myserial Return Code = 0 task pri tid runtime csw stksz stkuse last_checkin next_checkin idle 255 0 151917 47 64 34 0 0 main 127 1 2 59 512 188 0 0 ble_ll 0 2 0 14 80 56 0 0","title":"Examples"},{"location":"os/introduction/","text":"Introduction Welcome to Apache Mynewt Apache Mynewt is an operating system that makes it easy to develop applications for microcontroller environments where power and cost are driving factors. Examples of these devices are connected locks, lights, and wearables. Microcontroller environments have a number of characteristics that makes the operating system requirements for them unique: Low memory footprint: memory on these systems range from 8-16KB (on the low end) to 16MB (on the high end). Reduced code size: code often runs out of flash, and total available code size ranges from 64-128KB to 16-32MB. Low processing speed: processor speeds vary from 10-12MHz to 160-200MHz. Low power operation: devices operate in mostly sleeping mode, in order to conserve battery power and maximize power usage. As more and more devices get connected, these interconnected devices perform complex tasks. To perform these tasks, you need low-level operational functionality built into the operating system. Typically, connected devices built with these microcontrollers perform a myriad of functions: Networking Stacks: Bluetooth Low Energy and Thread Peripherals: PWM to drive motors, ADCs to measure sensor data, and RTCs to keep time. Scheduled Processing: actions must happen on a calendared or periodic basis. Apache Mynewt accomplishes all the above easily, by providing a complete operating system for constrained devices, including: A fully open-source Bluetooth Low Energy stack with both Host and Controller implementations. A pre-emptive, multi-tasking Real Time operating system kernel A Hardware Abstraction Layer (HAL) that abstracts the MCU's peripheral functions, allowing developers to easily write cross-platform code. Newt In order to provide all this functionality, and operate in an extremely low resource environment, Mynewt provides a very fine-grained source package management and build system tool, called newt . You can install newt for Mac OS , Linux , or Windows . Newt Manager In order to enable a user to communicate with remote instances of Mynewt OS and query, configure, and operate them, Mynewt provides an application tool called Newt Manager or newtmgr . You can install newtmgr for Mac OS , Linux , or Windows . Build your first Mynewt App with Newt With the introductions out of the way, now is a good time to get set up and started with your first Mynewt application. Happy Hacking!","title":"toc"},{"location":"os/introduction/#introduction","text":"","title":"Introduction"},{"location":"os/introduction/#welcome-to-apache-mynewt","text":"Apache Mynewt is an operating system that makes it easy to develop applications for microcontroller environments where power and cost are driving factors. Examples of these devices are connected locks, lights, and wearables. Microcontroller environments have a number of characteristics that makes the operating system requirements for them unique: Low memory footprint: memory on these systems range from 8-16KB (on the low end) to 16MB (on the high end). Reduced code size: code often runs out of flash, and total available code size ranges from 64-128KB to 16-32MB. Low processing speed: processor speeds vary from 10-12MHz to 160-200MHz. Low power operation: devices operate in mostly sleeping mode, in order to conserve battery power and maximize power usage. As more and more devices get connected, these interconnected devices perform complex tasks. To perform these tasks, you need low-level operational functionality built into the operating system. Typically, connected devices built with these microcontrollers perform a myriad of functions: Networking Stacks: Bluetooth Low Energy and Thread Peripherals: PWM to drive motors, ADCs to measure sensor data, and RTCs to keep time. Scheduled Processing: actions must happen on a calendared or periodic basis. Apache Mynewt accomplishes all the above easily, by providing a complete operating system for constrained devices, including: A fully open-source Bluetooth Low Energy stack with both Host and Controller implementations. A pre-emptive, multi-tasking Real Time operating system kernel A Hardware Abstraction Layer (HAL) that abstracts the MCU's peripheral functions, allowing developers to easily write cross-platform code.","title":"Welcome to Apache Mynewt"},{"location":"os/introduction/#newt","text":"In order to provide all this functionality, and operate in an extremely low resource environment, Mynewt provides a very fine-grained source package management and build system tool, called newt . You can install newt for Mac OS , Linux , or Windows .","title":"Newt"},{"location":"os/introduction/#newt-manager","text":"In order to enable a user to communicate with remote instances of Mynewt OS and query, configure, and operate them, Mynewt provides an application tool called Newt Manager or newtmgr . You can install newtmgr for Mac OS , Linux , or Windows .","title":"Newt Manager"},{"location":"os/introduction/#build-your-first-mynewt-app-with-newt","text":"With the introductions out of the way, now is a good time to get set up and started with your first Mynewt application. Happy Hacking!","title":"Build your first Mynewt App with Newt"},{"location":"os/os_user_guide/","text":"OS User Guide This guide provides comprehensive information about Mynewt OS, the real-time operating system for embedded systems. It is intended both for an embedded real-time software developer as well as higher-level applications developer wanting to understand the features and benefits of the system. Mynewt OS is highly composable and flexible. Only those features actually used by the application are compiled into the run-time image. Hence, the actual size of Mynewt is completely determined by the application. The guide covers all the features and services available in the OS and contains several examples showing how they can be used. Send us an email on the dev@ mailing list if you have comments or suggestions! If you haven't joined the mailing list, you will find the links here .","title":"toc"},{"location":"os/os_user_guide/#os-user-guide","text":"This guide provides comprehensive information about Mynewt OS, the real-time operating system for embedded systems. It is intended both for an embedded real-time software developer as well as higher-level applications developer wanting to understand the features and benefits of the system. Mynewt OS is highly composable and flexible. Only those features actually used by the application are compiled into the run-time image. Hence, the actual size of Mynewt is completely determined by the application. The guide covers all the features and services available in the OS and contains several examples showing how they can be used. Send us an email on the dev@ mailing list if you have comments or suggestions! If you haven't joined the mailing list, you will find the links here .","title":"OS User Guide"},{"location":"os/core_os/mynewt_os/","text":"Mynewt Core OS The Mynewt Core OS is a multitasking, preemptive real-time operating system combining a scheduler with typical RTOS features such as mutexes, semaphores, memory pools, etc. The Mynewt Core OS also provides a number of useful utilities such as a task watchdog, networking stack, memory buffers and time management API. Each of these features is described in detail in its own section of the manual. A multitasking, preemptive operating system is one in which a number of different tasks can be instantiated and assigned a priority, with higher priority tasks running before lower priority tasks. Furthermore, if a lower priority task is running and a higher priority task wants to run, the lower priority task is halted and the higher priority task is allowed to run. In other words, the lower priority task is preempted by the higher priority task. Why use an OS? You may ask yourself \"why do I need a multitasking preemptive OS\"? The answer may indeed be that you do not. Some applications are simple and only require a polling loop. Others are more complex and may require that certain jobs are executed in a timely manner or before other jobs are executed. If you have a simple polling loop, you cannot move on to service a job until the current job is done being serviced. With the Mynewt OS, the application developer need not worry about certain jobs taking too long or not executing in a timely fashion; the OS provides mechanisms to deal with these situations. Another benefit of using an OS is that it helps shield application developers from other application code being written; the developer does not have to worry (or has to worry less) about other application code behaving badly and causing undesirable behavior or preventing their code from executing properly. Other benefits of using an OS (and the Mynewt OS in particular) is that it also provides features that the developer would otherwise need to create on his/her own. Core OS Features Scheduler/context switching Time Tasks Event queues/callouts Semaphores Mutexes Memory pools Heap Mbufs Sanity Callouts Porting OS to other platforms Basic OS Application Creation Creating an application using the Mynewt Core OS is a relatively simple task. The main steps are: Install the basic Newt Tool structure (build structure) for your application. Create your BSP (Board Support Package). In your application main() function, call the sysinit() function to initialize the system and packages, perform application specific initialization, then wait and dispatch events from the OS default event queue in an infinite loop. (See System Configuration and Initialization for more details.) Initializing application modules and tasks can get somewhat complicated with RTOS's similar to Mynewt. Care must be taken that the API provided by a task are initialized prior to being called by another (higher priority) task. For example, take a simple application with two tasks (tasks 1 and 2, with task 1 higher priority than task 2). Task 2 provides an API which has a semaphore lock and this semaphore is initialized by task 2 when the task handler for task 2 is called. Task 1 is expected to call this API. Consider the sequence of events when the OS is started. The scheduler starts running and picks the highest priority task (task 1 in this case). The task handler function for task 1 is called and will keep running until it yields execution. Before yielding, code in the task 1 handler function calls the API provided by task 2. The semaphore being accessed in the task 2 API has yet to be initialized since the task 2 handler function has not had a chance to run! This will lead to undesirable behavior and will need to be addressed by the application developer. Note that the Mynewt OS does guard against internal API being called before the OS has started (they will return error) but it does not safeguard application defined objects from access prior to initialization. Example One way to avoid initialization issues like the one described above is for the application to initialize the objects that are accessed by multiple tasks before it initializes the tasks with the OS. The code example shown below illustrates this concept. The application initializes system and packages, calls an application specific \"task initialization\" function, and dispatches events from the default event queue. The application task initialization function is responsible for initializing all the data objects that each task exposes to the other tasks. The tasks themselves are also initialized at this time (by calling os_task_init() ). In the example, each task works in a ping-pong like fashion: task 1 wakes up, adds a token to semaphore 1 and then waits for a token from semaphore 2. Task 2 waits for a token on semaphore 1 and once it gets it, adds a token to semaphore 2. Notice that the semaphores are initialized by the application specific task initialization functions and not inside the task handler functions. If task 2 (being lower in priority than task 1) had called os_sem_init() for task2_sem inside task2_handler() , task 1 would have called os_sem_pend() using task2_sem before task2_sem was initialized. struct os_sem task1_sem ; struct os_sem task2_sem ; /* Task 1 handler function */ void task1_handler ( void *arg ) { while ( 1 ) { /* Release semaphore to task 2 */ os_sem_release ( &task1_sem ); /* Wait for semaphore from task 2 */ os_sem_pend ( &task2_sem , OS_TIMEOUT_NEVER ); } } /* Task 2 handler function */ void task2_handler ( void *arg ) { struct os_task *t ; while ( 1 ) { /* Wait for semaphore from task1 */ os_sem_pend ( &task1_sem , OS_TIMEOUT_NEVER ); /* Release task2 semaphore */ os_sem_release ( &task2_sem ); } } /* Initialize task 1 exposed data objects */ void task1_init ( void ) { /* Initialize task1 semaphore */ os_sem_init ( &task1_sem , 0 ); } /* Initialize task 2 exposed data objects */ void task2_init ( void ) { /* Initialize task1 semaphore */ os_sem_init ( &task2_sem , 0 ); } /** * init_app_tasks * * This function performs initializations that are required before tasks run. * * @return int 0 success; error otherwise. */ static int init_app_tasks ( void ) { /* * Call task specific initialization functions to initialize any shared objects * before initializing the tasks with the OS. */ task1_init (); task2_init (); /* * Initialize tasks 1 and 2 with the OS. */ os_task_init ( &task1 , \"task1\" , task1_handler , NULL , TASK1_PRIO , OS_WAIT_FOREVER , task1_stack , TASK1_STACK_SIZE ); os_task_init ( &task2 , \"task2\" , task2_handler , NULL , TASK2_PRIO , OS_WAIT_FOREVER , task2_stack , TASK2_STACK_SIZE ); return 0 ; } /** * main * * The main function for the application. This function initializes the system and packages, * calls the application specific task initialization function, then waits and dispatches * events from the OS default event queue in an infinite loop. */ int main ( int argc , char **arg ) { /* Perform system and package initialization */ sysinit (); /* Initialize application specific tasks */ init_app_tasks (); while ( 1 ) { os_eventq_run ( os_eventq_dflt_get ()); } /* main never returns */ } OS Functions The functions available at the OS level are: os_started","title":"toc"},{"location":"os/core_os/mynewt_os/#mynewt-core-os","text":"The Mynewt Core OS is a multitasking, preemptive real-time operating system combining a scheduler with typical RTOS features such as mutexes, semaphores, memory pools, etc. The Mynewt Core OS also provides a number of useful utilities such as a task watchdog, networking stack, memory buffers and time management API. Each of these features is described in detail in its own section of the manual. A multitasking, preemptive operating system is one in which a number of different tasks can be instantiated and assigned a priority, with higher priority tasks running before lower priority tasks. Furthermore, if a lower priority task is running and a higher priority task wants to run, the lower priority task is halted and the higher priority task is allowed to run. In other words, the lower priority task is preempted by the higher priority task.","title":"Mynewt Core OS"},{"location":"os/core_os/mynewt_os/#why-use-an-os","text":"You may ask yourself \"why do I need a multitasking preemptive OS\"? The answer may indeed be that you do not. Some applications are simple and only require a polling loop. Others are more complex and may require that certain jobs are executed in a timely manner or before other jobs are executed. If you have a simple polling loop, you cannot move on to service a job until the current job is done being serviced. With the Mynewt OS, the application developer need not worry about certain jobs taking too long or not executing in a timely fashion; the OS provides mechanisms to deal with these situations. Another benefit of using an OS is that it helps shield application developers from other application code being written; the developer does not have to worry (or has to worry less) about other application code behaving badly and causing undesirable behavior or preventing their code from executing properly. Other benefits of using an OS (and the Mynewt OS in particular) is that it also provides features that the developer would otherwise need to create on his/her own.","title":"Why use an OS?"},{"location":"os/core_os/mynewt_os/#core-os-features","text":"Scheduler/context switching Time Tasks Event queues/callouts Semaphores Mutexes Memory pools Heap Mbufs Sanity Callouts Porting OS to other platforms","title":"Core OS Features"},{"location":"os/core_os/mynewt_os/#basic-os-application-creation","text":"Creating an application using the Mynewt Core OS is a relatively simple task. The main steps are: Install the basic Newt Tool structure (build structure) for your application. Create your BSP (Board Support Package). In your application main() function, call the sysinit() function to initialize the system and packages, perform application specific initialization, then wait and dispatch events from the OS default event queue in an infinite loop. (See System Configuration and Initialization for more details.) Initializing application modules and tasks can get somewhat complicated with RTOS's similar to Mynewt. Care must be taken that the API provided by a task are initialized prior to being called by another (higher priority) task. For example, take a simple application with two tasks (tasks 1 and 2, with task 1 higher priority than task 2). Task 2 provides an API which has a semaphore lock and this semaphore is initialized by task 2 when the task handler for task 2 is called. Task 1 is expected to call this API. Consider the sequence of events when the OS is started. The scheduler starts running and picks the highest priority task (task 1 in this case). The task handler function for task 1 is called and will keep running until it yields execution. Before yielding, code in the task 1 handler function calls the API provided by task 2. The semaphore being accessed in the task 2 API has yet to be initialized since the task 2 handler function has not had a chance to run! This will lead to undesirable behavior and will need to be addressed by the application developer. Note that the Mynewt OS does guard against internal API being called before the OS has started (they will return error) but it does not safeguard application defined objects from access prior to initialization.","title":"Basic OS Application Creation"},{"location":"os/core_os/mynewt_os/#example","text":"One way to avoid initialization issues like the one described above is for the application to initialize the objects that are accessed by multiple tasks before it initializes the tasks with the OS. The code example shown below illustrates this concept. The application initializes system and packages, calls an application specific \"task initialization\" function, and dispatches events from the default event queue. The application task initialization function is responsible for initializing all the data objects that each task exposes to the other tasks. The tasks themselves are also initialized at this time (by calling os_task_init() ). In the example, each task works in a ping-pong like fashion: task 1 wakes up, adds a token to semaphore 1 and then waits for a token from semaphore 2. Task 2 waits for a token on semaphore 1 and once it gets it, adds a token to semaphore 2. Notice that the semaphores are initialized by the application specific task initialization functions and not inside the task handler functions. If task 2 (being lower in priority than task 1) had called os_sem_init() for task2_sem inside task2_handler() , task 1 would have called os_sem_pend() using task2_sem before task2_sem was initialized. struct os_sem task1_sem ; struct os_sem task2_sem ; /* Task 1 handler function */ void task1_handler ( void *arg ) { while ( 1 ) { /* Release semaphore to task 2 */ os_sem_release ( &task1_sem ); /* Wait for semaphore from task 2 */ os_sem_pend ( &task2_sem , OS_TIMEOUT_NEVER ); } } /* Task 2 handler function */ void task2_handler ( void *arg ) { struct os_task *t ; while ( 1 ) { /* Wait for semaphore from task1 */ os_sem_pend ( &task1_sem , OS_TIMEOUT_NEVER ); /* Release task2 semaphore */ os_sem_release ( &task2_sem ); } } /* Initialize task 1 exposed data objects */ void task1_init ( void ) { /* Initialize task1 semaphore */ os_sem_init ( &task1_sem , 0 ); } /* Initialize task 2 exposed data objects */ void task2_init ( void ) { /* Initialize task1 semaphore */ os_sem_init ( &task2_sem , 0 ); } /** * init_app_tasks * * This function performs initializations that are required before tasks run. * * @return int 0 success; error otherwise. */ static int init_app_tasks ( void ) { /* * Call task specific initialization functions to initialize any shared objects * before initializing the tasks with the OS. */ task1_init (); task2_init (); /* * Initialize tasks 1 and 2 with the OS. */ os_task_init ( &task1 , \"task1\" , task1_handler , NULL , TASK1_PRIO , OS_WAIT_FOREVER , task1_stack , TASK1_STACK_SIZE ); os_task_init ( &task2 , \"task2\" , task2_handler , NULL , TASK2_PRIO , OS_WAIT_FOREVER , task2_stack , TASK2_STACK_SIZE ); return 0 ; } /** * main * * The main function for the application. This function initializes the system and packages, * calls the application specific task initialization function, then waits and dispatches * events from the OS default event queue in an infinite loop. */ int main ( int argc , char **arg ) { /* Perform system and package initialization */ sysinit (); /* Initialize application specific tasks */ init_app_tasks (); while ( 1 ) { os_eventq_run ( os_eventq_dflt_get ()); } /* main never returns */ }","title":"Example"},{"location":"os/core_os/mynewt_os/#os-functions","text":"The functions available at the OS level are: os_started","title":"OS Functions"},{"location":"os/core_os/os_init/","text":"os_init void os_init ( void ) Initializes the OS. Must be called before the OS is started (i.e. os_start() is called). Arguments None Returned values None Notes The call to os_init() performs architecture and bsp initializations and initializes the idle task. This function does not start the OS, the OS time tick interrupt, or the scheduler.","title":"Os init"},{"location":"os/core_os/os_init/#os_init","text":"void os_init ( void ) Initializes the OS. Must be called before the OS is started (i.e. os_start() is called).","title":"os_init"},{"location":"os/core_os/os_init/#arguments","text":"None","title":"Arguments"},{"location":"os/core_os/os_init/#returned-values","text":"None","title":"Returned values"},{"location":"os/core_os/os_init/#notes","text":"The call to os_init() performs architecture and bsp initializations and initializes the idle task. This function does not start the OS, the OS time tick interrupt, or the scheduler.","title":"Notes"},{"location":"os/core_os/os_start/","text":"os_start void os_start ( void ) Starts the OS by initializing and enabling the OS time tick and starting the scheduler. This function does not return. Arguments None Returned values None (does not return). Notes Once os_start() has been called, context is switched to the highest priority task that was initialized prior to calling os_start() .","title":"Os start"},{"location":"os/core_os/os_start/#os_start","text":"void os_start ( void ) Starts the OS by initializing and enabling the OS time tick and starting the scheduler. This function does not return.","title":"os_start"},{"location":"os/core_os/os_start/#arguments","text":"None","title":"Arguments"},{"location":"os/core_os/os_start/#returned-values","text":"None (does not return).","title":"Returned values"},{"location":"os/core_os/os_start/#notes","text":"Once os_start() has been called, context is switched to the highest priority task that was initialized prior to calling os_start() .","title":"Notes"},{"location":"os/core_os/os_started/","text":"os_started int os_started ( void ) Returns 'true' (1) if the os has been started; 0 otherwise. Arguments None Returned values Integer value with 0 meaning the OS has not been started and 1 indicating the OS has been started (i.e. os_start() has been called).","title":"os_started"},{"location":"os/core_os/os_started/#os_started","text":"int os_started ( void ) Returns 'true' (1) if the os has been started; 0 otherwise.","title":"os_started"},{"location":"os/core_os/os_started/#arguments","text":"None","title":"Arguments"},{"location":"os/core_os/os_started/#returned-values","text":"Integer value with 0 meaning the OS has not been started and 1 indicating the OS has been started (i.e. os_start() has been called).","title":"Returned values"},{"location":"os/core_os/callout/callout/","text":"Callout Callouts are MyNewt OS timers. Description Callout is a way of setting up an OS timer. When the timer fires, it is delivered as an event to task's event queue. User would initialize their callout structure using os_callout_init() , or os_callout_func_init() and then arm it with os_callout_reset() . If user wants to cancel the timer before it expires, they can either use os_callout_reset() to arm it for later expiry, or stop it altogether by calling os_callout_stop() . There are 2 different options for data structure to use. First is struct os_callout , which is a bare-bones version. You would initialize this with os_callout_init() . Second option is struct os_callout_func . This you can use if you expect to have multiple different types of timers in your task, running concurrently. The structure contains a function pointer, and you would call that function from your task's event processing loop. Time unit when arming the timer is OS ticks. This rate of this ticker depends on the platform this is running on. You should use OS define OS_TICKS_PER_SEC to convert wallclock time to OS ticks. Callout timer fires out just once. For periodic timer type of operation you need to rearm it once it fires. Data structures struct os_callout { struct os_event c_ev ; struct os_eventq *c_evq ; uint32_t c_ticks ; TAILQ_ENTRY ( os_callout ) c_next ; }; Element Description c_ev Event structure of this callout c_evq Event queue where this callout is placed on timer expiry c_ticks OS tick amount when timer fires c_next Linkage to other unexpired callouts struct os_callout_func { struct os_callout cf_c ; os_callout_func_t cf_func ; void *cf_arg ; }; Element Description cf_c struct os_callout. See above cf_func Function pointer which should be called by event queue processing cf_arg Generic void * argument to that function List of Functions The functions available in callout are: Function Description os_callout_func_init Initializes the given callout function struct. os_callout_init Initializes the given callout struct. os_callout_queued Checks whether the given callout has been armed. os_callout_reset Resets the callout to happen in the given number of OS ticks. os_callout_stop Disarms a timer.","title":"toc"},{"location":"os/core_os/callout/callout/#callout","text":"Callouts are MyNewt OS timers.","title":"Callout"},{"location":"os/core_os/callout/callout/#description","text":"Callout is a way of setting up an OS timer. When the timer fires, it is delivered as an event to task's event queue. User would initialize their callout structure using os_callout_init() , or os_callout_func_init() and then arm it with os_callout_reset() . If user wants to cancel the timer before it expires, they can either use os_callout_reset() to arm it for later expiry, or stop it altogether by calling os_callout_stop() . There are 2 different options for data structure to use. First is struct os_callout , which is a bare-bones version. You would initialize this with os_callout_init() . Second option is struct os_callout_func . This you can use if you expect to have multiple different types of timers in your task, running concurrently. The structure contains a function pointer, and you would call that function from your task's event processing loop. Time unit when arming the timer is OS ticks. This rate of this ticker depends on the platform this is running on. You should use OS define OS_TICKS_PER_SEC to convert wallclock time to OS ticks. Callout timer fires out just once. For periodic timer type of operation you need to rearm it once it fires.","title":"Description"},{"location":"os/core_os/callout/callout/#data-structures","text":"struct os_callout { struct os_event c_ev ; struct os_eventq *c_evq ; uint32_t c_ticks ; TAILQ_ENTRY ( os_callout ) c_next ; }; Element Description c_ev Event structure of this callout c_evq Event queue where this callout is placed on timer expiry c_ticks OS tick amount when timer fires c_next Linkage to other unexpired callouts struct os_callout_func { struct os_callout cf_c ; os_callout_func_t cf_func ; void *cf_arg ; }; Element Description cf_c struct os_callout. See above cf_func Function pointer which should be called by event queue processing cf_arg Generic void * argument to that function","title":"Data structures"},{"location":"os/core_os/callout/callout/#list-of-functions","text":"The functions available in callout are: Function Description os_callout_func_init Initializes the given callout function struct. os_callout_init Initializes the given callout struct. os_callout_queued Checks whether the given callout has been armed. os_callout_reset Resets the callout to happen in the given number of OS ticks. os_callout_stop Disarms a timer.","title":"List of Functions"},{"location":"os/core_os/callout/os_callout_func_init/","text":"os_callout_func_init void os_callout_func_init ( struct os_callout_func *cf , struct os_eventq *evq , os_callout_func_t timo_func , void *ev_arg ) Initializes the given struct os_callout_func . Data structure is filled in with elements given as argument. Arguments Arguments Description cf Pointer to os_callout_func being initialized evq Event queue where this gets delivered to timo_func Timeout function. Event processing should call this ev_arg Generic argument for the event Returned values N/A Notes The same notes as with os_callout_init() . Example struct os_callout_func g_native_cputimer ; struct os_eventq g_native_cputime_evq ; void native_cputimer_cb ( void *arg ); /* Initialize the callout function */ os_callout_func_init ( &g_native_cputimer , &g_native_cputime_evq , native_cputimer_cb , NULL );","title":"os_callout_func_init"},{"location":"os/core_os/callout/os_callout_func_init/#os_callout_func_init","text":"void os_callout_func_init ( struct os_callout_func *cf , struct os_eventq *evq , os_callout_func_t timo_func , void *ev_arg ) Initializes the given struct os_callout_func . Data structure is filled in with elements given as argument.","title":" os_callout_func_init "},{"location":"os/core_os/callout/os_callout_func_init/#arguments","text":"Arguments Description cf Pointer to os_callout_func being initialized evq Event queue where this gets delivered to timo_func Timeout function. Event processing should call this ev_arg Generic argument for the event","title":"Arguments"},{"location":"os/core_os/callout/os_callout_func_init/#returned-values","text":"N/A","title":"Returned values"},{"location":"os/core_os/callout/os_callout_func_init/#notes","text":"The same notes as with os_callout_init() .","title":"Notes"},{"location":"os/core_os/callout/os_callout_func_init/#example","text":"struct os_callout_func g_native_cputimer ; struct os_eventq g_native_cputime_evq ; void native_cputimer_cb ( void *arg ); /* Initialize the callout function */ os_callout_func_init ( &g_native_cputimer , &g_native_cputime_evq , native_cputimer_cb , NULL );","title":"Example"},{"location":"os/core_os/callout/os_callout_init/","text":"os_callout_init void os_callout_init ( struct os_callout *c , struct os_eventq *evq , void *ev_arg ) Initializes struct os_callout . Event type will be set to OS_EVENT_T_TIMER . Arguments Arguments Description c Pointer to os_callout to initialize evq Event queue where this gets delivered to ev_arg Generic argument which is filled in for the event Returned values N/A Notes Be careful not to call this if the callout is armed, because that will mess up the list of pending callouts. Or if the timer has already fired, it will mess up the event queue where the callout was delivered to. Example struct os_eventq my_evq ; struct os_callout my_callouts [ 8 ]; for ( i = 0 ; i < 8 ; i++ ) { os_callout_init ( &my_callouts [ i ], &my_evq , ( void * ) i ); }","title":"os_callout_init"},{"location":"os/core_os/callout/os_callout_init/#os_callout_init","text":"void os_callout_init ( struct os_callout *c , struct os_eventq *evq , void *ev_arg ) Initializes struct os_callout . Event type will be set to OS_EVENT_T_TIMER .","title":"os_callout_init "},{"location":"os/core_os/callout/os_callout_init/#arguments","text":"Arguments Description c Pointer to os_callout to initialize evq Event queue where this gets delivered to ev_arg Generic argument which is filled in for the event","title":"Arguments"},{"location":"os/core_os/callout/os_callout_init/#returned-values","text":"N/A","title":"Returned values"},{"location":"os/core_os/callout/os_callout_init/#notes","text":"Be careful not to call this if the callout is armed, because that will mess up the list of pending callouts. Or if the timer has already fired, it will mess up the event queue where the callout was delivered to.","title":"Notes"},{"location":"os/core_os/callout/os_callout_init/#example","text":"struct os_eventq my_evq ; struct os_callout my_callouts [ 8 ]; for ( i = 0 ; i < 8 ; i++ ) { os_callout_init ( &my_callouts [ i ], &my_evq , ( void * ) i ); }","title":"Example"},{"location":"os/core_os/callout/os_callout_queued/","text":"os_callout_queued int os_callout_queued ( struct os_callout *c ) Tells whether the callout has been armed or not. Arguments Arguments Description c Pointer to callout being checked Returned values 0: timer is not armed non-zero: timer is armed","title":"os_callout_queued"},{"location":"os/core_os/callout/os_callout_queued/#os_callout_queued","text":"int os_callout_queued ( struct os_callout *c ) Tells whether the callout has been armed or not.","title":"os_callout_queued"},{"location":"os/core_os/callout/os_callout_queued/#arguments","text":"Arguments Description c Pointer to callout being checked","title":"Arguments"},{"location":"os/core_os/callout/os_callout_queued/#returned-values","text":"0: timer is not armed non-zero: timer is armed","title":"Returned values"},{"location":"os/core_os/callout/os_callout_reset/","text":"os_callout_reset void os_callout_reset ( struct os_callout *c , int32_t timo ) Resets the callout to happen timo in OS ticks. Arguments Arguments Description c Pointer to os_callout being reset timo OS ticks the timer is being set to Returned values N/A Notes Example /* Re-start the timer (run every 50 msecs) */ os_callout_reset ( &g_bletest_timer . cf_c , OS_TICKS_PER_SEC / 20 );","title":"os_callout_reset"},{"location":"os/core_os/callout/os_callout_reset/#os_callout_reset","text":"void os_callout_reset ( struct os_callout *c , int32_t timo ) Resets the callout to happen timo in OS ticks.","title":" os_callout_reset "},{"location":"os/core_os/callout/os_callout_reset/#arguments","text":"Arguments Description c Pointer to os_callout being reset timo OS ticks the timer is being set to","title":"Arguments"},{"location":"os/core_os/callout/os_callout_reset/#returned-values","text":"N/A","title":"Returned values"},{"location":"os/core_os/callout/os_callout_reset/#notes","text":"","title":"Notes"},{"location":"os/core_os/callout/os_callout_reset/#example","text":"/* Re-start the timer (run every 50 msecs) */ os_callout_reset ( &g_bletest_timer . cf_c , OS_TICKS_PER_SEC / 20 );","title":"Example"},{"location":"os/core_os/callout/os_callout_stop/","text":"os_callout_stop void os_callout_stop ( struct os_callout *c ) Disarms a timer. Arguments Arguments Description c Pointer to os_callout being stopped Returned values N/A Example struct os_callout_func g_native_cputimer ; os_callout_stop ( &g_native_cputimer . cf_c );","title":"os_callout_stop"},{"location":"os/core_os/callout/os_callout_stop/#os_callout_stop","text":"void os_callout_stop ( struct os_callout *c ) Disarms a timer.","title":" os_callout_stop "},{"location":"os/core_os/callout/os_callout_stop/#arguments","text":"Arguments Description c Pointer to os_callout being stopped","title":"Arguments"},{"location":"os/core_os/callout/os_callout_stop/#returned-values","text":"N/A","title":"Returned values"},{"location":"os/core_os/callout/os_callout_stop/#example","text":"struct os_callout_func g_native_cputimer ; os_callout_stop ( &g_native_cputimer . cf_c );","title":"Example"},{"location":"os/core_os/context_switch/context_switch/","text":"Scheduler/Context Switching Scheduler's job is to maintain the list of tasks and decide which one should be running next. Description Task states can be running , ready to run or sleeping . When a task is running , the CPU is executing in that task's context. The program counter (PC) is pointing to instructions that task wants to execute and the stack pointer (SP) is pointing to that task's stack. A task which is ready to run wants to get on the CPU to do its work. A task which is sleeping has no more work to do. It's waiting for someone or something else to wake it up. The Scheduler algorithm is simple: from among the tasks which are ready to run, pick the the one with highest priority (lowest numeric value in task's t_prio field), and make its state running . Tasks which are either running or ready to run are kept in a linked list g_os_run_list . This list is ordered by priority. Tasks which are sleeping are kept in a linked list g_os_sleep_list . The scheduler has a CPU architecture specific component; this code is responsible for swapping in the task which should be running . This process is called context switch. During context switching the state of the CPU (e.g. registers) for the currently running task is stored and the new task is swapped in. List of Functions The functions available in context_switch are: Function Description os_sched Performs context switch if needed. os_arch_ctx_sw Change the state of a given task to running . os_sched_ctx_sw_hook Performs task accounting when context switching. os_sched_get_current_task Returns the pointer to the task which is currently running . os_sched_insert Insert a task into scheduler's ready to run list. os_sched_next_task Returns the pointer to highest priority task from the list which are ready to run . os_sched_os_timer_exp Inform scheduler that OS time has moved forward. os_sched_remove Stops a task and removes it from all the OS task lists. os_sched_resort Inform scheduler that the priority of the given task has changed and the ready to run list should be re-sorted. os_sched_set_current_task Sets the given task to running . os_sched_sleep The given task's state is changed from ready to run to sleeping . os_sched_wakeup Called to make task ready to run . If task is sleeping , it is woken up.","title":"toc"},{"location":"os/core_os/context_switch/context_switch/#schedulercontext-switching","text":"Scheduler's job is to maintain the list of tasks and decide which one should be running next.","title":"Scheduler/Context Switching"},{"location":"os/core_os/context_switch/context_switch/#description","text":"Task states can be running , ready to run or sleeping . When a task is running , the CPU is executing in that task's context. The program counter (PC) is pointing to instructions that task wants to execute and the stack pointer (SP) is pointing to that task's stack. A task which is ready to run wants to get on the CPU to do its work. A task which is sleeping has no more work to do. It's waiting for someone or something else to wake it up. The Scheduler algorithm is simple: from among the tasks which are ready to run, pick the the one with highest priority (lowest numeric value in task's t_prio field), and make its state running . Tasks which are either running or ready to run are kept in a linked list g_os_run_list . This list is ordered by priority. Tasks which are sleeping are kept in a linked list g_os_sleep_list . The scheduler has a CPU architecture specific component; this code is responsible for swapping in the task which should be running . This process is called context switch. During context switching the state of the CPU (e.g. registers) for the currently running task is stored and the new task is swapped in.","title":"Description"},{"location":"os/core_os/context_switch/context_switch/#list-of-functions","text":"The functions available in context_switch are: Function Description os_sched Performs context switch if needed. os_arch_ctx_sw Change the state of a given task to running . os_sched_ctx_sw_hook Performs task accounting when context switching. os_sched_get_current_task Returns the pointer to the task which is currently running . os_sched_insert Insert a task into scheduler's ready to run list. os_sched_next_task Returns the pointer to highest priority task from the list which are ready to run . os_sched_os_timer_exp Inform scheduler that OS time has moved forward. os_sched_remove Stops a task and removes it from all the OS task lists. os_sched_resort Inform scheduler that the priority of the given task has changed and the ready to run list should be re-sorted. os_sched_set_current_task Sets the given task to running . os_sched_sleep The given task's state is changed from ready to run to sleeping . os_sched_wakeup Called to make task ready to run . If task is sleeping , it is woken up.","title":"List of Functions"},{"location":"os/core_os/context_switch/os_arch_ctx_sw/","text":"os_arch_ctx_sw void os_arch_ctx_sw ( struct os_task *next_t ) Change the state of task pointed by next_t to be running . Arguments Arguments Description next_t Pointer to task which must run next Returned values N/A Notes This would get called from another task's context. Example void os_sched ( struct os_task *next_t ) { os_sr_t sr ; OS_ENTER_CRITICAL ( sr ); if ( !next_t ) { next_t = os_sched_next_task (); } if ( next_t != g_current_task ) { os_arch_ctx_sw ( next_t ); } OS_EXIT_CRITICAL ( sr ); }","title":"os_arch_ctx_sw"},{"location":"os/core_os/context_switch/os_arch_ctx_sw/#os_arch_ctx_sw","text":"void os_arch_ctx_sw ( struct os_task *next_t ) Change the state of task pointed by next_t to be running .","title":" os_arch_ctx_sw "},{"location":"os/core_os/context_switch/os_arch_ctx_sw/#arguments","text":"Arguments Description next_t Pointer to task which must run next","title":"Arguments"},{"location":"os/core_os/context_switch/os_arch_ctx_sw/#returned-values","text":"N/A","title":"Returned values"},{"location":"os/core_os/context_switch/os_arch_ctx_sw/#notes","text":"This would get called from another task's context.","title":"Notes"},{"location":"os/core_os/context_switch/os_arch_ctx_sw/#example","text":"void os_sched ( struct os_task *next_t ) { os_sr_t sr ; OS_ENTER_CRITICAL ( sr ); if ( !next_t ) { next_t = os_sched_next_task (); } if ( next_t != g_current_task ) { os_arch_ctx_sw ( next_t ); } OS_EXIT_CRITICAL ( sr ); }","title":"Example"},{"location":"os/core_os/context_switch/os_sched/","text":"os_sched void os_sched ( struct os_task *next_t ) Performs context switch if needed. If next_t is set, that task will be made running . If next_t is NULL , highest priority ready to run is swapped in. This function can be called when new tasks were made ready to run or if the current task is moved to sleeping state. This function will call the architecture specific routine to swap in the new task. Arguments Arguments Description next_t Pointer to task which must run next (optional) Returned values N/A Notes Interrupts must be disabled when calling this. Example os_error_t os_mutex_release ( struct os_mutex *mu ) { ... OS_EXIT_CRITICAL ( sr ); /* Re-schedule if needed */ if ( resched ) { os_sched ( rdy ); } return OS_OK ; }","title":"os_sched"},{"location":"os/core_os/context_switch/os_sched/#os_sched","text":"void os_sched ( struct os_task *next_t ) Performs context switch if needed. If next_t is set, that task will be made running . If next_t is NULL , highest priority ready to run is swapped in. This function can be called when new tasks were made ready to run or if the current task is moved to sleeping state. This function will call the architecture specific routine to swap in the new task.","title":" os_sched "},{"location":"os/core_os/context_switch/os_sched/#arguments","text":"Arguments Description next_t Pointer to task which must run next (optional)","title":"Arguments"},{"location":"os/core_os/context_switch/os_sched/#returned-values","text":"N/A","title":"Returned values"},{"location":"os/core_os/context_switch/os_sched/#notes","text":"Interrupts must be disabled when calling this.","title":"Notes"},{"location":"os/core_os/context_switch/os_sched/#example","text":"os_error_t os_mutex_release ( struct os_mutex *mu ) { ... OS_EXIT_CRITICAL ( sr ); /* Re-schedule if needed */ if ( resched ) { os_sched ( rdy ); } return OS_OK ; }","title":"Example"},{"location":"os/core_os/context_switch/os_sched_ctx_sw_hook/","text":"os_sched_ctx_sw_hook void os_sched_ctx_sw_hook ( struct os_task *next_t ) Performs task accounting when context switching. This function must be called from the architecture specific context switching routine os_arch_ctx_sw() before resuming execution of the running task. Arguments N/A Returned values N/A Notes Example void os_arch_ctx_sw ( struct os_task *t ) { os_sched_ctx_sw_hook ( t ); /* Set PendSV interrupt pending bit to force context switch */ SCB->ICSR = SCB_ICSR_PENDSVSET_Msk ; }","title":"os_sched_ctx_sw_hook"},{"location":"os/core_os/context_switch/os_sched_ctx_sw_hook/#os_sched_ctx_sw_hook","text":"void os_sched_ctx_sw_hook ( struct os_task *next_t ) Performs task accounting when context switching. This function must be called from the architecture specific context switching routine os_arch_ctx_sw() before resuming execution of the running task.","title":" os_sched_ctx_sw_hook "},{"location":"os/core_os/context_switch/os_sched_ctx_sw_hook/#arguments","text":"N/A","title":"Arguments"},{"location":"os/core_os/context_switch/os_sched_ctx_sw_hook/#returned-values","text":"N/A","title":"Returned values"},{"location":"os/core_os/context_switch/os_sched_ctx_sw_hook/#notes","text":"","title":"Notes"},{"location":"os/core_os/context_switch/os_sched_ctx_sw_hook/#example","text":"void os_arch_ctx_sw ( struct os_task *t ) { os_sched_ctx_sw_hook ( t ); /* Set PendSV interrupt pending bit to force context switch */ SCB->ICSR = SCB_ICSR_PENDSVSET_Msk ; }","title":"Example"},{"location":"os/core_os/context_switch/os_sched_get_current_task/","text":"os_sched_get_current_task struct os_task *os_sched_get_current_task ( void ) Returns the pointer to task which is currently running . Arguments N/A Returned values See description. Notes Example void os_time_delay ( int32_t osticks ) { os_sr_t sr ; if ( osticks > 0 ) { OS_ENTER_CRITICAL ( sr ); os_sched_sleep ( os_sched_get_current_task (), ( os_time_t ) osticks ); OS_EXIT_CRITICAL ( sr ); os_sched ( NULL ); } }","title":"os_sched_get_current_task"},{"location":"os/core_os/context_switch/os_sched_get_current_task/#os_sched_get_current_task","text":"struct os_task *os_sched_get_current_task ( void ) Returns the pointer to task which is currently running .","title":" os_sched_get_current_task "},{"location":"os/core_os/context_switch/os_sched_get_current_task/#arguments","text":"N/A","title":"Arguments"},{"location":"os/core_os/context_switch/os_sched_get_current_task/#returned-values","text":"See description.","title":"Returned values"},{"location":"os/core_os/context_switch/os_sched_get_current_task/#notes","text":"","title":"Notes"},{"location":"os/core_os/context_switch/os_sched_get_current_task/#example","text":"void os_time_delay ( int32_t osticks ) { os_sr_t sr ; if ( osticks > 0 ) { OS_ENTER_CRITICAL ( sr ); os_sched_sleep ( os_sched_get_current_task (), ( os_time_t ) osticks ); OS_EXIT_CRITICAL ( sr ); os_sched ( NULL ); } }","title":"Example"},{"location":"os/core_os/context_switch/os_sched_insert/","text":"os_sched_insert os_error_t os_sched_insert ( struct os_task *t ) Insert task into scheduler's ready to run list. Arguments Arguments Description t Pointer to task Returned values Returns OS_EINVAL if task state is not READY . Returns 0 on success. Notes You probably don't need to call this.","title":"os_sched_insert"},{"location":"os/core_os/context_switch/os_sched_insert/#os_sched_insert","text":"os_error_t os_sched_insert ( struct os_task *t ) Insert task into scheduler's ready to run list.","title":" os_sched_insert "},{"location":"os/core_os/context_switch/os_sched_insert/#arguments","text":"Arguments Description t Pointer to task","title":"Arguments"},{"location":"os/core_os/context_switch/os_sched_insert/#returned-values","text":"Returns OS_EINVAL if task state is not READY . Returns 0 on success.","title":"Returned values"},{"location":"os/core_os/context_switch/os_sched_insert/#notes","text":"You probably don't need to call this.","title":"Notes"},{"location":"os/core_os/context_switch/os_sched_next_task/","text":"os_sched_next_task struct os_task *os_sched_next_task ( void ) Returns the pointer to highest priority task from the list which are ready to run . Arguments N/A Returned values See description. Notes Should be called with interrupts disabled.","title":"os_sched_next_task"},{"location":"os/core_os/context_switch/os_sched_next_task/#os_sched_next_task","text":"struct os_task *os_sched_next_task ( void ) Returns the pointer to highest priority task from the list which are ready to run .","title":" os_sched_next_task "},{"location":"os/core_os/context_switch/os_sched_next_task/#arguments","text":"N/A","title":"Arguments"},{"location":"os/core_os/context_switch/os_sched_next_task/#returned-values","text":"See description.","title":"Returned values"},{"location":"os/core_os/context_switch/os_sched_next_task/#notes","text":"Should be called with interrupts disabled.","title":"Notes"},{"location":"os/core_os/context_switch/os_sched_os_timer_exp/","text":"os_sched_os_timer_exp void os_sched_os_timer_exp ( void ) Inform scheduler that OS time has moved forward, and it should inspect tasks which are sleeping to check whether they should be moved to g_run_list or not. This function should be called from code which handles moving OS time forward. After calling it, the highest priority task which is ready to run might've changed, so call to os_sched() should be done. Arguments N/A Returned values N/A Notes Example void timer_handler ( void ) { os_time_tick (); os_callout_tick (); os_sched_os_timer_exp (); os_sched ( NULL ); }","title":"os_sched_os_timer_exp"},{"location":"os/core_os/context_switch/os_sched_os_timer_exp/#os_sched_os_timer_exp","text":"void os_sched_os_timer_exp ( void ) Inform scheduler that OS time has moved forward, and it should inspect tasks which are sleeping to check whether they should be moved to g_run_list or not. This function should be called from code which handles moving OS time forward. After calling it, the highest priority task which is ready to run might've changed, so call to os_sched() should be done.","title":" os_sched_os_timer_exp "},{"location":"os/core_os/context_switch/os_sched_os_timer_exp/#arguments","text":"N/A","title":"Arguments"},{"location":"os/core_os/context_switch/os_sched_os_timer_exp/#returned-values","text":"N/A","title":"Returned values"},{"location":"os/core_os/context_switch/os_sched_os_timer_exp/#notes","text":"","title":"Notes"},{"location":"os/core_os/context_switch/os_sched_os_timer_exp/#example","text":"void timer_handler ( void ) { os_time_tick (); os_callout_tick (); os_sched_os_timer_exp (); os_sched ( NULL ); }","title":"Example"},{"location":"os/core_os/context_switch/os_sched_remove/","text":"os_sched_remove int os_sched_remove ( struct os_task *t ) Stops and removes task t . The function removes the task from the g_os_task_list task list. It also removes the task from one of the following task list: g_os_run_list if the task is in the Ready state. g_os_sleep_list if the task is in the Sleep state. Arguments Arguments Description t Pointer to the os_task structure for the task to be removed. Returned values OS_OK - The task is removed successfully. Notes This function must be called with all interrupts disabled. Example The os_task_remove function calls the os_sched_remove function to remove a task: int os_task_remove ( struct os_task *t ) { int rc ; os_sr_t sr ; /* Add error checking code to ensure task can removed. */ /* Call os_sched_remove to remove the task. */ OS_ENTER_CRITICAL ( sr ); rc = os_sched_remove ( t ); OS_EXIT_CRITICAL ( sr ); return rc ; }","title":"os_sched_remove"},{"location":"os/core_os/context_switch/os_sched_remove/#os_sched_remove","text":"int os_sched_remove ( struct os_task *t ) Stops and removes task t . The function removes the task from the g_os_task_list task list. It also removes the task from one of the following task list: g_os_run_list if the task is in the Ready state. g_os_sleep_list if the task is in the Sleep state.","title":" os_sched_remove "},{"location":"os/core_os/context_switch/os_sched_remove/#arguments","text":"Arguments Description t Pointer to the os_task structure for the task to be removed.","title":"Arguments"},{"location":"os/core_os/context_switch/os_sched_remove/#returned-values","text":"OS_OK - The task is removed successfully.","title":"Returned values"},{"location":"os/core_os/context_switch/os_sched_remove/#notes","text":"This function must be called with all interrupts disabled.","title":"Notes"},{"location":"os/core_os/context_switch/os_sched_remove/#example","text":"The os_task_remove function calls the os_sched_remove function to remove a task: int os_task_remove ( struct os_task *t ) { int rc ; os_sr_t sr ; /* Add error checking code to ensure task can removed. */ /* Call os_sched_remove to remove the task. */ OS_ENTER_CRITICAL ( sr ); rc = os_sched_remove ( t ); OS_EXIT_CRITICAL ( sr ); return rc ; }","title":"Example"},{"location":"os/core_os/context_switch/os_sched_resort/","text":"os_sched_resort void os_sched_resort ( struct os_task *t ) Inform scheduler that the priority of the task t has changed (e.g. in order to avoid priority inversion), and the ready to run list should be re-sorted. Arguments Arguments Description t Pointer to a task whose priority has changed Returned values N/A Notes t must be ready to run before calling this. Example os_error_t os_mutex_pend ( struct os_mutex *mu , uint32_t timeout ) { .... /* Change priority of owner if needed */ if ( mu->mu_owner->t_prio > current->t_prio ) { mu->mu_owner->t_prio = current->t_prio ; os_sched_resort ( mu->mu_owner ); } .... }","title":"os_sched_resort"},{"location":"os/core_os/context_switch/os_sched_resort/#os_sched_resort","text":"void os_sched_resort ( struct os_task *t ) Inform scheduler that the priority of the task t has changed (e.g. in order to avoid priority inversion), and the ready to run list should be re-sorted.","title":" os_sched_resort "},{"location":"os/core_os/context_switch/os_sched_resort/#arguments","text":"Arguments Description t Pointer to a task whose priority has changed","title":"Arguments"},{"location":"os/core_os/context_switch/os_sched_resort/#returned-values","text":"N/A","title":"Returned values"},{"location":"os/core_os/context_switch/os_sched_resort/#notes","text":"t must be ready to run before calling this.","title":"Notes"},{"location":"os/core_os/context_switch/os_sched_resort/#example","text":"os_error_t os_mutex_pend ( struct os_mutex *mu , uint32_t timeout ) { .... /* Change priority of owner if needed */ if ( mu->mu_owner->t_prio > current->t_prio ) { mu->mu_owner->t_prio = current->t_prio ; os_sched_resort ( mu->mu_owner ); } .... }","title":"Example"},{"location":"os/core_os/context_switch/os_sched_set_current_task/","text":"os_sched_set_current_task void os_sched_set_current_task ( struct os_task *t ) Sets the currently running task to t . This is called from architecture specific context switching code to update scheduler state. Call is made when state of the task t is made running . Arguments Arguments Description t Pointer to a task Returned values N/A Notes This function simply sets the global variable holding the currently running task. It does not perform a context switch or change the os run or sleep list.","title":"os_sched_set_current_task"},{"location":"os/core_os/context_switch/os_sched_set_current_task/#os_sched_set_current_task","text":"void os_sched_set_current_task ( struct os_task *t ) Sets the currently running task to t . This is called from architecture specific context switching code to update scheduler state. Call is made when state of the task t is made running .","title":" os_sched_set_current_task "},{"location":"os/core_os/context_switch/os_sched_set_current_task/#arguments","text":"Arguments Description t Pointer to a task","title":"Arguments"},{"location":"os/core_os/context_switch/os_sched_set_current_task/#returned-values","text":"N/A","title":"Returned values"},{"location":"os/core_os/context_switch/os_sched_set_current_task/#notes","text":"This function simply sets the global variable holding the currently running task. It does not perform a context switch or change the os run or sleep list.","title":"Notes"},{"location":"os/core_os/context_switch/os_sched_sleep/","text":"os_sched_sleep int os_sched_sleep ( struct os_task *t , os_time_t nticks ) Task t state is changed from ready to run to sleeping . Sleep time will be specified in nticks . Task will be woken up after sleep timer expires, unless there are other signals causing it to wake up. If nticks is set to OS_TIMEOUT_NEVER , task never wakes up with a sleep timer. Arguments Arguments Description t Pointer to task nticks Number of ticks to sleep in OS ticks Returned values Returns 0 on success. Notes Must be called with interrupts disabled. Example struct os_event * os_eventq_get ( struct os_eventq *evq ) { struct os_event *ev ; os_sr_t sr ; OS_ENTER_CRITICAL ( sr ); pull_one : ev = STAILQ_FIRST ( &evq->evq_list ); if ( ev ) { STAILQ_REMOVE ( &evq->evq_list , ev , os_event , ev_next ); ev->ev_queued = 0 ; } else { evq->evq_task = os_sched_get_current_task (); os_sched_sleep ( evq->evq_task , OS_TIMEOUT_NEVER ); OS_EXIT_CRITICAL ( sr ); os_sched ( NULL ); OS_ENTER_CRITICAL ( sr ); evq->evq_task = NULL ; goto pull_one ; } OS_EXIT_CRITICAL ( sr ); return ( ev ); }","title":"os_sched_sleep"},{"location":"os/core_os/context_switch/os_sched_sleep/#os_sched_sleep","text":"int os_sched_sleep ( struct os_task *t , os_time_t nticks ) Task t state is changed from ready to run to sleeping . Sleep time will be specified in nticks . Task will be woken up after sleep timer expires, unless there are other signals causing it to wake up. If nticks is set to OS_TIMEOUT_NEVER , task never wakes up with a sleep timer.","title":" os_sched_sleep "},{"location":"os/core_os/context_switch/os_sched_sleep/#arguments","text":"Arguments Description t Pointer to task nticks Number of ticks to sleep in OS ticks","title":"Arguments"},{"location":"os/core_os/context_switch/os_sched_sleep/#returned-values","text":"Returns 0 on success.","title":"Returned values"},{"location":"os/core_os/context_switch/os_sched_sleep/#notes","text":"Must be called with interrupts disabled.","title":"Notes"},{"location":"os/core_os/context_switch/os_sched_sleep/#example","text":"struct os_event * os_eventq_get ( struct os_eventq *evq ) { struct os_event *ev ; os_sr_t sr ; OS_ENTER_CRITICAL ( sr ); pull_one : ev = STAILQ_FIRST ( &evq->evq_list ); if ( ev ) { STAILQ_REMOVE ( &evq->evq_list , ev , os_event , ev_next ); ev->ev_queued = 0 ; } else { evq->evq_task = os_sched_get_current_task (); os_sched_sleep ( evq->evq_task , OS_TIMEOUT_NEVER ); OS_EXIT_CRITICAL ( sr ); os_sched ( NULL ); OS_ENTER_CRITICAL ( sr ); evq->evq_task = NULL ; goto pull_one ; } OS_EXIT_CRITICAL ( sr ); return ( ev ); }","title":"Example"},{"location":"os/core_os/context_switch/os_sched_wakeup/","text":"os_sched_wakeup int os_sched_wakeup ( struct os_task *t ) Called to make task ready to run . If task is sleeping , it is woken up. Arguments Arguments Description t Pointer to task Returned values Returns 0 on success. Notes Example void os_eventq_put ( struct os_eventq *evq , struct os_event *ev ) { .... /* If task waiting on event, wake it up. */ resched = 0 ; if ( evq->evq_task ) { os_sched_wakeup ( evq->evq_task ); evq->evq_task = NULL ; resched = 1 ; } .... }","title":"os_sched_wakeup"},{"location":"os/core_os/context_switch/os_sched_wakeup/#os_sched_wakeup","text":"int os_sched_wakeup ( struct os_task *t ) Called to make task ready to run . If task is sleeping , it is woken up.","title":" os_sched_wakeup "},{"location":"os/core_os/context_switch/os_sched_wakeup/#arguments","text":"Arguments Description t Pointer to task","title":"Arguments"},{"location":"os/core_os/context_switch/os_sched_wakeup/#returned-values","text":"Returns 0 on success.","title":"Returned values"},{"location":"os/core_os/context_switch/os_sched_wakeup/#notes","text":"","title":"Notes"},{"location":"os/core_os/context_switch/os_sched_wakeup/#example","text":"void os_eventq_put ( struct os_eventq *evq , struct os_event *ev ) { .... /* If task waiting on event, wake it up. */ resched = 0 ; if ( evq->evq_task ) { os_sched_wakeup ( evq->evq_task ); evq->evq_task = NULL ; resched = 1 ; } .... }","title":"Example"},{"location":"os/core_os/cputime/os_cputime/","text":"CPU Time The MyNewt cputime module provides high resolution time and timer support. Description The cputime API provides high resolution time and timer support. The module must be initialized, using the os_cputime_init() function, with the clock frequency to use. The module uses the hal_timer API, defined in hal/hal_timer.h, to access the hardware timers. It uses the hardware timer number specified by the OS_CPUTIME_TIMER_NUM system configuration setting. Data Structures The module uses the following data structures: uint32_t to represent cputime . Only the lower 32 bits of a 64 timer are used. struct hal_timer to represent a cputime timer. List of Functions The functions available in cputime are: Function Description os_cputime_delay_nsecs Delays for a specified number of nanoseconds. os_cputime_delay_ticks Delays for a specified number of ticks. os_cputime_delay_usecs Delays for a specified number of microseconds. os_cputime_get32 Gets the current value of the cpu time. os_cputime_init Initializes the cputime module. os_cputime_nsecs_to_ticks Converts the specified number of nanoseconds to number of ticks. os_cputime_ticks_to_nsecs Converts the specified number of ticks to number of nanoseconds. os_cputime_ticks_to_usecs Converts the specified number of ticks to number of microseconds. os_cputime_timer_init Initializes a timer. os_cputime_timer_relative Sets a timer to expire in the specified number of microseconds from the current time. os_cputime_timer_start Sets a timer to expire at the specified cputime. os_cputime_timer_stop Stops a timer from running. os_cputime_usecs_to_ticks Converts the specified number of microseconds to number of ticks. List of Macros These macros should be used to evaluate the time with respect to each other. CPUIME_LT(t1,t2) -- evaluates to true if t1 is before t2 in time. CPUTIME_GT(t1,t2) -- evaluates to true if t1 is after t2 in time CPUTIME_LEQ(t1,t2) -- evaluates to true if t1 is on or before t2 in time. CPUTIME_GEQ(t1,t2) -- evaluates to true if t1 is on or after t2 in time.","title":"toc"},{"location":"os/core_os/cputime/os_cputime/#cpu-time","text":"The MyNewt cputime module provides high resolution time and timer support.","title":"CPU Time"},{"location":"os/core_os/cputime/os_cputime/#description","text":"The cputime API provides high resolution time and timer support. The module must be initialized, using the os_cputime_init() function, with the clock frequency to use. The module uses the hal_timer API, defined in hal/hal_timer.h, to access the hardware timers. It uses the hardware timer number specified by the OS_CPUTIME_TIMER_NUM system configuration setting.","title":"Description"},{"location":"os/core_os/cputime/os_cputime/#data-structures","text":"The module uses the following data structures: uint32_t to represent cputime . Only the lower 32 bits of a 64 timer are used. struct hal_timer to represent a cputime timer.","title":"Data Structures"},{"location":"os/core_os/cputime/os_cputime/#list-of-functions","text":"The functions available in cputime are: Function Description os_cputime_delay_nsecs Delays for a specified number of nanoseconds. os_cputime_delay_ticks Delays for a specified number of ticks. os_cputime_delay_usecs Delays for a specified number of microseconds. os_cputime_get32 Gets the current value of the cpu time. os_cputime_init Initializes the cputime module. os_cputime_nsecs_to_ticks Converts the specified number of nanoseconds to number of ticks. os_cputime_ticks_to_nsecs Converts the specified number of ticks to number of nanoseconds. os_cputime_ticks_to_usecs Converts the specified number of ticks to number of microseconds. os_cputime_timer_init Initializes a timer. os_cputime_timer_relative Sets a timer to expire in the specified number of microseconds from the current time. os_cputime_timer_start Sets a timer to expire at the specified cputime. os_cputime_timer_stop Stops a timer from running. os_cputime_usecs_to_ticks Converts the specified number of microseconds to number of ticks.","title":"List of Functions"},{"location":"os/core_os/cputime/os_cputime/#list-of-macros","text":"These macros should be used to evaluate the time with respect to each other. CPUIME_LT(t1,t2) -- evaluates to true if t1 is before t2 in time. CPUTIME_GT(t1,t2) -- evaluates to true if t1 is after t2 in time CPUTIME_LEQ(t1,t2) -- evaluates to true if t1 is on or before t2 in time. CPUTIME_GEQ(t1,t2) -- evaluates to true if t1 is on or after t2 in time.","title":"List of Macros"},{"location":"os/core_os/cputime/os_cputime_delay_nsecs/","text":"os_cputime_delay_nsecs void os_cputime_delay_nsecs ( uint32_t nsecs ) Waits for a specified number of nanoseconds to elapse before returning. Arguments Arguments Description nsecs Number of nanoseconds to delay for. Returned values N/A Notes Example Delays for 250000 nsecs: os_cputime_delay_nsecs ( 250000 )","title":"os_cputime_delay_nsecs"},{"location":"os/core_os/cputime/os_cputime_delay_nsecs/#os_cputime_delay_nsecs","text":"void os_cputime_delay_nsecs ( uint32_t nsecs ) Waits for a specified number of nanoseconds to elapse before returning.","title":"os_cputime_delay_nsecs"},{"location":"os/core_os/cputime/os_cputime_delay_nsecs/#arguments","text":"Arguments Description nsecs Number of nanoseconds to delay for.","title":"Arguments"},{"location":"os/core_os/cputime/os_cputime_delay_nsecs/#returned-values","text":"N/A","title":"Returned values"},{"location":"os/core_os/cputime/os_cputime_delay_nsecs/#notes","text":"","title":"Notes"},{"location":"os/core_os/cputime/os_cputime_delay_nsecs/#example","text":"Delays for 250000 nsecs: os_cputime_delay_nsecs ( 250000 )","title":"Example"},{"location":"os/core_os/cputime/os_cputime_delay_ticks/","text":"os_cputime_delay_ticks void os_cputime_delay_ticks ( uint32_t ticks ) Waits for a specified number of ticks to elapse before returning. Arguments Arguments Description ticks Number of ticks to delay for. Returned values N/A Notes Example Delays for 100000 ticks: os_cputime_delay_ticks ( 100000 )","title":"os_cputime_delay_ticks"},{"location":"os/core_os/cputime/os_cputime_delay_ticks/#os_cputime_delay_ticks","text":"void os_cputime_delay_ticks ( uint32_t ticks ) Waits for a specified number of ticks to elapse before returning.","title":"os_cputime_delay_ticks"},{"location":"os/core_os/cputime/os_cputime_delay_ticks/#arguments","text":"Arguments Description ticks Number of ticks to delay for.","title":"Arguments"},{"location":"os/core_os/cputime/os_cputime_delay_ticks/#returned-values","text":"N/A","title":"Returned values"},{"location":"os/core_os/cputime/os_cputime_delay_ticks/#notes","text":"","title":"Notes"},{"location":"os/core_os/cputime/os_cputime_delay_ticks/#example","text":"Delays for 100000 ticks: os_cputime_delay_ticks ( 100000 )","title":"Example"},{"location":"os/core_os/cputime/os_cputime_delay_usecs/","text":"os_cputime_delay_usecs void os_cputime_delay_usecs ( uint32_t usecs ) Waits for a specified number of microseconds to elapse before returning. Arguments Arguments Description usecs Number of microseconds to delay for. Returned values N/A Notes Example Delays for 250000 usecs: os_cputime_delay_usecs ( 250000 )","title":"os_cputime_delay_usecs"},{"location":"os/core_os/cputime/os_cputime_delay_usecs/#os_cputime_delay_usecs","text":"void os_cputime_delay_usecs ( uint32_t usecs ) Waits for a specified number of microseconds to elapse before returning.","title":"os_cputime_delay_usecs"},{"location":"os/core_os/cputime/os_cputime_delay_usecs/#arguments","text":"Arguments Description usecs Number of microseconds to delay for.","title":"Arguments"},{"location":"os/core_os/cputime/os_cputime_delay_usecs/#returned-values","text":"N/A","title":"Returned values"},{"location":"os/core_os/cputime/os_cputime_delay_usecs/#notes","text":"","title":"Notes"},{"location":"os/core_os/cputime/os_cputime_delay_usecs/#example","text":"Delays for 250000 usecs: os_cputime_delay_usecs ( 250000 )","title":"Example"},{"location":"os/core_os/cputime/os_cputime_get32/","text":"os_cputime_get32 uint32_t os_cputime_get32 ( void ) Gets the current cputime. If a timer is 64 bits, only the lower 32 bit is returned. Arguments N/A Returned values The current cputime. Notes Example uint32 cur_cputime ; cur_cputime = os_cputime_get32 ();","title":"os_cputime_get32"},{"location":"os/core_os/cputime/os_cputime_get32/#os_cputime_get32","text":"uint32_t os_cputime_get32 ( void ) Gets the current cputime. If a timer is 64 bits, only the lower 32 bit is returned.","title":"os_cputime_get32"},{"location":"os/core_os/cputime/os_cputime_get32/#arguments","text":"N/A","title":"Arguments"},{"location":"os/core_os/cputime/os_cputime_get32/#returned-values","text":"The current cputime.","title":"Returned values"},{"location":"os/core_os/cputime/os_cputime_get32/#notes","text":"","title":"Notes"},{"location":"os/core_os/cputime/os_cputime_get32/#example","text":"uint32 cur_cputime ; cur_cputime = os_cputime_get32 ();","title":"Example"},{"location":"os/core_os/cputime/os_cputime_init/","text":"os_cputime_init int os_cputime_init ( uint32_t clock_freq ) Initializes the cputime module with the clock frequency (in HZ) to use for the timer resolution. It configures the hardware timer specified by the OS_CPUTIME_TIMER_NUM sysconfig value to run at the specified clock frequency. Arguments Arguments Description clock_freq Clock frequency, in HZ, for the timer resolution. Returned values 0 on success and -1 on error. Notes This function must be called after os_init is called. It should only be called once and before any other timer API and hardware timers are used. Example A BSP package usually calls this function and uses the OS_CPUTIME_FREQUENCY sysconfig value for the clock frequency argument: int rc rc = os_cputime_init ( MYNEWT_VAL ( OS_CPUTIME_FREQUENCY ));","title":"os_cputime_init"},{"location":"os/core_os/cputime/os_cputime_init/#os_cputime_init","text":"int os_cputime_init ( uint32_t clock_freq ) Initializes the cputime module with the clock frequency (in HZ) to use for the timer resolution. It configures the hardware timer specified by the OS_CPUTIME_TIMER_NUM sysconfig value to run at the specified clock frequency.","title":"os_cputime_init"},{"location":"os/core_os/cputime/os_cputime_init/#arguments","text":"Arguments Description clock_freq Clock frequency, in HZ, for the timer resolution.","title":"Arguments"},{"location":"os/core_os/cputime/os_cputime_init/#returned-values","text":"0 on success and -1 on error.","title":"Returned values"},{"location":"os/core_os/cputime/os_cputime_init/#notes","text":"This function must be called after os_init is called. It should only be called once and before any other timer API and hardware timers are used.","title":"Notes"},{"location":"os/core_os/cputime/os_cputime_init/#example","text":"A BSP package usually calls this function and uses the OS_CPUTIME_FREQUENCY sysconfig value for the clock frequency argument: int rc rc = os_cputime_init ( MYNEWT_VAL ( OS_CPUTIME_FREQUENCY ));","title":"Example"},{"location":"os/core_os/cputime/os_cputime_nsecs_to_ticks/","text":"os_cputime_nsecs_to_ticks uint32_t os_cputime_nsecs_to_ticks ( uint32_t nsecs ) Converts a specified number of nanoseconds to cputime ticks. Arguments Arguments Description nsecs Number of nanoseconds to convert to ticks. Returned values The number of ticks in nsecs nanoseconds. Notes Example uint32_t num_ticks ; num_ticks = os_cputime_nsecs_to_ticks ( 1000000 );","title":"os_cputime_nsecs_to_ticks"},{"location":"os/core_os/cputime/os_cputime_nsecs_to_ticks/#os_cputime_nsecs_to_ticks","text":"uint32_t os_cputime_nsecs_to_ticks ( uint32_t nsecs ) Converts a specified number of nanoseconds to cputime ticks.","title":"os_cputime_nsecs_to_ticks"},{"location":"os/core_os/cputime/os_cputime_nsecs_to_ticks/#arguments","text":"Arguments Description nsecs Number of nanoseconds to convert to ticks.","title":"Arguments"},{"location":"os/core_os/cputime/os_cputime_nsecs_to_ticks/#returned-values","text":"The number of ticks in nsecs nanoseconds.","title":"Returned values"},{"location":"os/core_os/cputime/os_cputime_nsecs_to_ticks/#notes","text":"","title":"Notes"},{"location":"os/core_os/cputime/os_cputime_nsecs_to_ticks/#example","text":"uint32_t num_ticks ; num_ticks = os_cputime_nsecs_to_ticks ( 1000000 );","title":"Example"},{"location":"os/core_os/cputime/os_cputime_ticks_to_nsecs/","text":"os_cputime_ticks_to_nsecs uint32_t os_cputime_ticks_to_nsecs ( uint32_t ticks ) Converts cputime ticks to nanoseconds. Arguments Arguments Description ticks Number of cputime ticks to convert to nanoseconds. Returned values The number of nanoseconds in ticks number of ticks. Notes Example uint32_t num_nsecs ; num_nsecs = os_cputime_ticks_to_nsecs ( 1000000 );","title":"os_cputime_ticks_to_nsecs"},{"location":"os/core_os/cputime/os_cputime_ticks_to_nsecs/#os_cputime_ticks_to_nsecs","text":"uint32_t os_cputime_ticks_to_nsecs ( uint32_t ticks ) Converts cputime ticks to nanoseconds.","title":"os_cputime_ticks_to_nsecs"},{"location":"os/core_os/cputime/os_cputime_ticks_to_nsecs/#arguments","text":"Arguments Description ticks Number of cputime ticks to convert to nanoseconds.","title":"Arguments"},{"location":"os/core_os/cputime/os_cputime_ticks_to_nsecs/#returned-values","text":"The number of nanoseconds in ticks number of ticks.","title":"Returned values"},{"location":"os/core_os/cputime/os_cputime_ticks_to_nsecs/#notes","text":"","title":"Notes"},{"location":"os/core_os/cputime/os_cputime_ticks_to_nsecs/#example","text":"uint32_t num_nsecs ; num_nsecs = os_cputime_ticks_to_nsecs ( 1000000 );","title":"Example"},{"location":"os/core_os/cputime/os_cputime_ticks_to_usecs/","text":"os_cputime_ticks_to_usecs uint32_t os_cputime_ticks_to_usecs ( uint32_t ticks ) Converts a specified number of cputime ticks to microseconds. Arguments Arguments Description ticks Number of cputime ticks to convert to microseconds. Returned values The number of microseconds in ticks number of ticks. Notes Example uint32_t num_usecs ; num_usecs = os_cputime_ticks_to_usecs ( 1000000 );","title":"os_cputime_ticks_to_usecs"},{"location":"os/core_os/cputime/os_cputime_ticks_to_usecs/#os_cputime_ticks_to_usecs","text":"uint32_t os_cputime_ticks_to_usecs ( uint32_t ticks ) Converts a specified number of cputime ticks to microseconds.","title":"os_cputime_ticks_to_usecs"},{"location":"os/core_os/cputime/os_cputime_ticks_to_usecs/#arguments","text":"Arguments Description ticks Number of cputime ticks to convert to microseconds.","title":"Arguments"},{"location":"os/core_os/cputime/os_cputime_ticks_to_usecs/#returned-values","text":"The number of microseconds in ticks number of ticks.","title":"Returned values"},{"location":"os/core_os/cputime/os_cputime_ticks_to_usecs/#notes","text":"","title":"Notes"},{"location":"os/core_os/cputime/os_cputime_ticks_to_usecs/#example","text":"uint32_t num_usecs ; num_usecs = os_cputime_ticks_to_usecs ( 1000000 );","title":"Example"},{"location":"os/core_os/cputime/os_cputime_timer_init/","text":"os_cputime_timer_init void os_cputime_timer_init ( struct hal_timer *timer , hal_timer_cb fp , void *arg ) Initializes a cputime timer, indicated by timer , with a pointer to a callback function to call when the timer expires. When an optional opaque argument is specified, it is passed to the timer callback function. The callback function has the following prototype: void hal_timer_cb ( void *arg ) Arguments Arguments Description timer Pointer to the hal_timer to initialize. This value cannot be NULL. fp Pointer to the callback function to call when the timer expires. This value cannot be NULL. arg Optional opaque argument to pass to the hal timer callback function. Returned values N/A Notes Example Example of ble_ll setting up a response timer: ble_ll_wfr_timer_exp ( void *arg ) { int rx_start ; uint8_t lls ; ... /* If we have started a reception, there is nothing to do here */ if ( !rx_start ) { switch ( lls ) { case BLE_LL_STATE_ADV : ble_ll_adv_wfr_timer_exp (); break ; ... /* Do nothing here. Fall through intentional */ case BLE_LL_STATE_INITIATING : default : break ; } } } void ble_ll_init ( void ) { ... os_cputime_timer_init ( &g_ble_ll_data . ll_wfr_timer , ble_ll_wfr_timer_exp , NULL ); ... }","title":"os_cputime_timer_init"},{"location":"os/core_os/cputime/os_cputime_timer_init/#os_cputime_timer_init","text":"void os_cputime_timer_init ( struct hal_timer *timer , hal_timer_cb fp , void *arg ) Initializes a cputime timer, indicated by timer , with a pointer to a callback function to call when the timer expires. When an optional opaque argument is specified, it is passed to the timer callback function. The callback function has the following prototype: void hal_timer_cb ( void *arg )","title":"os_cputime_timer_init"},{"location":"os/core_os/cputime/os_cputime_timer_init/#arguments","text":"Arguments Description timer Pointer to the hal_timer to initialize. This value cannot be NULL. fp Pointer to the callback function to call when the timer expires. This value cannot be NULL. arg Optional opaque argument to pass to the hal timer callback function.","title":"Arguments"},{"location":"os/core_os/cputime/os_cputime_timer_init/#returned-values","text":"N/A","title":"Returned values"},{"location":"os/core_os/cputime/os_cputime_timer_init/#notes","text":"","title":"Notes"},{"location":"os/core_os/cputime/os_cputime_timer_init/#example","text":"Example of ble_ll setting up a response timer: ble_ll_wfr_timer_exp ( void *arg ) { int rx_start ; uint8_t lls ; ... /* If we have started a reception, there is nothing to do here */ if ( !rx_start ) { switch ( lls ) { case BLE_LL_STATE_ADV : ble_ll_adv_wfr_timer_exp (); break ; ... /* Do nothing here. Fall through intentional */ case BLE_LL_STATE_INITIATING : default : break ; } } } void ble_ll_init ( void ) { ... os_cputime_timer_init ( &g_ble_ll_data . ll_wfr_timer , ble_ll_wfr_timer_exp , NULL ); ... }","title":"Example"},{"location":"os/core_os/cputime/os_cputime_timer_relative/","text":"os_cputime_timer_relative void os_cputime_timer_relative ( struct hal_timer *timer , uint32_t usecs ) Sets a timer to expire in the specified number of microseconds from the current time. The callback function for the timer is called when the timer expires. Arguments Arguments Description timer Pointer to an initialized hal_timer. usecs The number of microseconds to set the timer to expire from now. Returned values N/A Notes timer must be initialized using the os_cputime_timer_init() function before setting up a timer. Example ` struct hal_timer mytimer ; ... os_cputime_timer_relative ( &mytimer , 100 );","title":"os_cputime_timer_relative"},{"location":"os/core_os/cputime/os_cputime_timer_relative/#os_cputime_timer_relative","text":"void os_cputime_timer_relative ( struct hal_timer *timer , uint32_t usecs ) Sets a timer to expire in the specified number of microseconds from the current time. The callback function for the timer is called when the timer expires.","title":"os_cputime_timer_relative"},{"location":"os/core_os/cputime/os_cputime_timer_relative/#arguments","text":"Arguments Description timer Pointer to an initialized hal_timer. usecs The number of microseconds to set the timer to expire from now.","title":"Arguments"},{"location":"os/core_os/cputime/os_cputime_timer_relative/#returned-values","text":"N/A","title":"Returned values"},{"location":"os/core_os/cputime/os_cputime_timer_relative/#notes","text":"timer must be initialized using the os_cputime_timer_init() function before setting up a timer.","title":"Notes"},{"location":"os/core_os/cputime/os_cputime_timer_relative/#example","text":"` struct hal_timer mytimer ; ... os_cputime_timer_relative ( &mytimer , 100 );","title":"Example"},{"location":"os/core_os/cputime/os_cputime_timer_start/","text":"os_cputime_timer_start void os_cputime_timer_start ( struct hal_timer *timer , uint32_t cputime ) Sets a timer to expire at the specified cputime. The callback function for the timer is called when the timer expires. Arguments Arguments Description timer Pointer to an initialized hal_timer. cputime The cputime when the timer expires. Returned values N/A Notes timer must be initialized using the os_cputime_timer_init() function before setting up a timer. Example void ble_ll_wfr_enable ( uint32_t cputime ) { os_cputime_timer_start ( &g_ble_ll_data . ll_wfr_timer , cputime ); }","title":"os_cputime_timer_start"},{"location":"os/core_os/cputime/os_cputime_timer_start/#os_cputime_timer_start","text":"void os_cputime_timer_start ( struct hal_timer *timer , uint32_t cputime ) Sets a timer to expire at the specified cputime. The callback function for the timer is called when the timer expires.","title":"os_cputime_timer_start"},{"location":"os/core_os/cputime/os_cputime_timer_start/#arguments","text":"Arguments Description timer Pointer to an initialized hal_timer. cputime The cputime when the timer expires.","title":"Arguments"},{"location":"os/core_os/cputime/os_cputime_timer_start/#returned-values","text":"N/A","title":"Returned values"},{"location":"os/core_os/cputime/os_cputime_timer_start/#notes","text":"timer must be initialized using the os_cputime_timer_init() function before setting up a timer.","title":"Notes"},{"location":"os/core_os/cputime/os_cputime_timer_start/#example","text":"void ble_ll_wfr_enable ( uint32_t cputime ) { os_cputime_timer_start ( &g_ble_ll_data . ll_wfr_timer , cputime ); }","title":"Example"},{"location":"os/core_os/cputime/os_cputime_timer_stop/","text":"os_cputime_timer_stop void os_cputime_timer_stop ( struct hal_timer *timer ) Stops a timer from running. The timer is removed from the timer queue and interrupts are disabled if there are no more timers on the timer queue. Arguments Arguments Description timer Pointer to the timer to stop. Returned values N/A Notes Example void ble_ll_wfr_disable ( void ) { os_cputime_timer_stop ( &g_ble_ll_data . ll_wfr_timer ); }","title":"os_cputime_timer_stop"},{"location":"os/core_os/cputime/os_cputime_timer_stop/#os_cputime_timer_stop","text":"void os_cputime_timer_stop ( struct hal_timer *timer ) Stops a timer from running. The timer is removed from the timer queue and interrupts are disabled if there are no more timers on the timer queue.","title":"os_cputime_timer_stop"},{"location":"os/core_os/cputime/os_cputime_timer_stop/#arguments","text":"Arguments Description timer Pointer to the timer to stop.","title":"Arguments"},{"location":"os/core_os/cputime/os_cputime_timer_stop/#returned-values","text":"N/A","title":"Returned values"},{"location":"os/core_os/cputime/os_cputime_timer_stop/#notes","text":"","title":"Notes"},{"location":"os/core_os/cputime/os_cputime_timer_stop/#example","text":"void ble_ll_wfr_disable ( void ) { os_cputime_timer_stop ( &g_ble_ll_data . ll_wfr_timer ); }","title":"Example"},{"location":"os/core_os/cputime/os_cputime_usecs_to_ticks/","text":"os_cputime_usecs_to_ticks uint32_t os_cputime_usecs_to_ticks ( uint32_t usecs ) Converts a specified number of microseconds to cputime ticks. Arguments Arguments Description usecs Number of microseconds to convert to ticks. Returned values The number of ticks in usecs nanoseconds. Notes Example uint32_t num_ticks ; num_ticks = os_cputime_usecs_to_ticks ( 100 );","title":"os_cputime_usecs_to_ticks"},{"location":"os/core_os/cputime/os_cputime_usecs_to_ticks/#os_cputime_usecs_to_ticks","text":"uint32_t os_cputime_usecs_to_ticks ( uint32_t usecs ) Converts a specified number of microseconds to cputime ticks.","title":"os_cputime_usecs_to_ticks"},{"location":"os/core_os/cputime/os_cputime_usecs_to_ticks/#arguments","text":"Arguments Description usecs Number of microseconds to convert to ticks.","title":"Arguments"},{"location":"os/core_os/cputime/os_cputime_usecs_to_ticks/#returned-values","text":"The number of ticks in usecs nanoseconds.","title":"Returned values"},{"location":"os/core_os/cputime/os_cputime_usecs_to_ticks/#notes","text":"","title":"Notes"},{"location":"os/core_os/cputime/os_cputime_usecs_to_ticks/#example","text":"uint32_t num_ticks ; num_ticks = os_cputime_usecs_to_ticks ( 100 );","title":"Example"},{"location":"os/core_os/event_queue/event_queue/","text":"Event Queues An event queue allows a task to serialize incoming events and simplify event processing. Events are stored in a queue and a task removes and processes an event from the queue. An event is processed in the context of this task. Events may be generated by OS callouts , interrupt handlers, and other tasks. Description Mynewt's event queue model uses callback functions to process events. Each event is associated with a callback function that is called to process the event. This model enables a library package, that uses events in its implementation but does not have real-time timing requirements, to use an application event queue instead of creating a dedicated event queue and task to process its events. The callback function executes in the context of the task that the application creates to manage the event queue. This model reduces an application's memory requirement because memory must be allocated for the task's stack when a task is created. A package that has real-time timing requirements and must run at a specific task priority should create a dedicated event queue and task to process its events. In the Mynewt model, a package defines its events and implements the callback functions for the events. A package that does not have real-time timing requirements should use Mynewt's default event queue for its events. The callback function for an event from the Mynewt default event queue is executed in the context of the application main task. A package can, optionally, export a function that allows an application to specify the event queue for the package to use. (See the example in the os_eventq_designate() function description on how to write such a function.) The application task handler that manages the event queue simply pulls events from the event queue and executes the event's callback function in its context. A common way that Mynewt applications or packages process events from an event queue is to have a task that executes in an infinite loop and calls the os_eventq_get() function to dequeue and return the event from the head of the event queue. The task then calls the event callback function to process the event. The os_eventq_get() function puts the task in to the sleeping state when there are no events on the queue. (See Scheduler for more information on task execution states.) Other tasks (or interrupts) call the os_eventq_put() function to add an event to the queue. The os_eventq_put() function determines whether a task is blocked waiting for an event on the queue and puts the task into the ready-to-run state. A task can use the os_eventq_run() wrapper function that calls the os_eventq_get() function to dequeue an event from the queue and then calls the event callback function to process the event. Note: Only one task should consume or block waiting for events from an event queue. The os_callout subsystem uses events for timer expiration notification. Data structures The os_event structure defines an event and has the following fields: struct os_event { uint8_t ev_queued ; os_event_fn *ev_cb ; void *ev_arg ; STAILQ_ENTRY ( os_event ) ev_next ; }; Element Description ev_queued Internal field that indicates whether this event is currently linked to an event queue ev_cb Pointer to the callback function to call to process this event ev_arg Pointer to an optional opaque data that the callback function uses to process this event ev_next Linkage attaching this event to an event queue An event callback function has the following function prototype: typedef void os_event_fn ( struct os_event *ev ); A pointer to the os_event structure for the event is passed as an argument to the callback function. Notes: If the memory for the os_event structure is dynamically allocated: You must not free the memory for an event that is currently on an event queue. You must free the memory in the callback function after it completes processing the event. You must set the callback function for an event when you initialize the event. For example, here is an example of a statically-initialized event in the NimBLE host: static void ble_hs_event_tx_notify ( struct os_event *ev ); /** OS event - triggers tx of pending notifications and indications. */ static struct os_event ble_hs_ev_tx_notifications = { . ev_cb = ble_hs_event_tx_notify , }; The os_eventq structure defines an event queue and has the following fields: struct os_eventq { struct os_task *evq_task ; STAILQ_HEAD (, os_event ) evq_list ; }; Element Description evq_task Pointer to the task, if any, that is waiting (in the sleeping state) for the os_eventq_get() function to return an event evq_list Head of the list of events in this queue You must call the os_eventq_init() function to initialize an event queue before you can add events to the queue. List of Functions The functions available in the Event Queue feature are: Function Description os_eventq_init Initializes an event queue. os_eventq_inited Indicates whether an event queue has been initialized. os_eventq_get Dequeues an event from the head of an event queue. The calling task blocks (in the sleeping state) when the event queue is empty. os_eventq_put Enqueues an event at the tail of an event queue and puts a task waiting for an event on the queue into the ready-to-run state. os_eventq_remove Removes an event from an event queue. os_eventq_dflt_get Gets the default event queue. os_eventq_designate Reassigns a package's current event queue to a new event queue. os_eventq_run Wrapper function that dequeues an event from an event queue and calls the callbck function for the event.","title":"toc"},{"location":"os/core_os/event_queue/event_queue/#event-queues","text":"An event queue allows a task to serialize incoming events and simplify event processing. Events are stored in a queue and a task removes and processes an event from the queue. An event is processed in the context of this task. Events may be generated by OS callouts , interrupt handlers, and other tasks.","title":"Event Queues"},{"location":"os/core_os/event_queue/event_queue/#description","text":"Mynewt's event queue model uses callback functions to process events. Each event is associated with a callback function that is called to process the event. This model enables a library package, that uses events in its implementation but does not have real-time timing requirements, to use an application event queue instead of creating a dedicated event queue and task to process its events. The callback function executes in the context of the task that the application creates to manage the event queue. This model reduces an application's memory requirement because memory must be allocated for the task's stack when a task is created. A package that has real-time timing requirements and must run at a specific task priority should create a dedicated event queue and task to process its events. In the Mynewt model, a package defines its events and implements the callback functions for the events. A package that does not have real-time timing requirements should use Mynewt's default event queue for its events. The callback function for an event from the Mynewt default event queue is executed in the context of the application main task. A package can, optionally, export a function that allows an application to specify the event queue for the package to use. (See the example in the os_eventq_designate() function description on how to write such a function.) The application task handler that manages the event queue simply pulls events from the event queue and executes the event's callback function in its context. A common way that Mynewt applications or packages process events from an event queue is to have a task that executes in an infinite loop and calls the os_eventq_get() function to dequeue and return the event from the head of the event queue. The task then calls the event callback function to process the event. The os_eventq_get() function puts the task in to the sleeping state when there are no events on the queue. (See Scheduler for more information on task execution states.) Other tasks (or interrupts) call the os_eventq_put() function to add an event to the queue. The os_eventq_put() function determines whether a task is blocked waiting for an event on the queue and puts the task into the ready-to-run state. A task can use the os_eventq_run() wrapper function that calls the os_eventq_get() function to dequeue an event from the queue and then calls the event callback function to process the event. Note: Only one task should consume or block waiting for events from an event queue. The os_callout subsystem uses events for timer expiration notification.","title":"Description"},{"location":"os/core_os/event_queue/event_queue/#data-structures","text":"The os_event structure defines an event and has the following fields: struct os_event { uint8_t ev_queued ; os_event_fn *ev_cb ; void *ev_arg ; STAILQ_ENTRY ( os_event ) ev_next ; }; Element Description ev_queued Internal field that indicates whether this event is currently linked to an event queue ev_cb Pointer to the callback function to call to process this event ev_arg Pointer to an optional opaque data that the callback function uses to process this event ev_next Linkage attaching this event to an event queue An event callback function has the following function prototype: typedef void os_event_fn ( struct os_event *ev ); A pointer to the os_event structure for the event is passed as an argument to the callback function. Notes: If the memory for the os_event structure is dynamically allocated: You must not free the memory for an event that is currently on an event queue. You must free the memory in the callback function after it completes processing the event. You must set the callback function for an event when you initialize the event. For example, here is an example of a statically-initialized event in the NimBLE host: static void ble_hs_event_tx_notify ( struct os_event *ev ); /** OS event - triggers tx of pending notifications and indications. */ static struct os_event ble_hs_ev_tx_notifications = { . ev_cb = ble_hs_event_tx_notify , }; The os_eventq structure defines an event queue and has the following fields: struct os_eventq { struct os_task *evq_task ; STAILQ_HEAD (, os_event ) evq_list ; }; Element Description evq_task Pointer to the task, if any, that is waiting (in the sleeping state) for the os_eventq_get() function to return an event evq_list Head of the list of events in this queue You must call the os_eventq_init() function to initialize an event queue before you can add events to the queue.","title":"Data structures"},{"location":"os/core_os/event_queue/event_queue/#list-of-functions","text":"The functions available in the Event Queue feature are: Function Description os_eventq_init Initializes an event queue. os_eventq_inited Indicates whether an event queue has been initialized. os_eventq_get Dequeues an event from the head of an event queue. The calling task blocks (in the sleeping state) when the event queue is empty. os_eventq_put Enqueues an event at the tail of an event queue and puts a task waiting for an event on the queue into the ready-to-run state. os_eventq_remove Removes an event from an event queue. os_eventq_dflt_get Gets the default event queue. os_eventq_designate Reassigns a package's current event queue to a new event queue. os_eventq_run Wrapper function that dequeues an event from an event queue and calls the callbck function for the event.","title":"List of Functions"},{"location":"os/core_os/event_queue/os_eventq_designate/","text":"os_eventq_designate void os_eventq_designate ( struct os_eventq **cur_evq , struct os_eventq *new_evq , struct os_event *start_ev ) Reassigns a package's current event queue pointer to point to a new event queue. If a startup event is specified, the event is added to the new event queue and removed from the current event queue. Arguments Arguments Description cur_evq Current event queue pointer to reassign new_evq New event queue to use for the package start_ev Start event to add to the new event queue Returned values None Notes Example This example shows the mgmt_evq_set() function that the mgmt/newtmgr package implements. The function allows an application to specify an event queue for newtmgr to use. The mgmt_evq_set() function calls the os_eventq_designate() function to reassign the nmgr_evq to the event queue that the application specifies. void mgmt_evq_set ( struct os_eventq *evq ) { os_eventq_designate ( &nmgr_evq , evq , NULL ); }","title":"os_eventq_designate"},{"location":"os/core_os/event_queue/os_eventq_designate/#os_eventq_designate","text":"void os_eventq_designate ( struct os_eventq **cur_evq , struct os_eventq *new_evq , struct os_event *start_ev ) Reassigns a package's current event queue pointer to point to a new event queue. If a startup event is specified, the event is added to the new event queue and removed from the current event queue.","title":" os_eventq_designate"},{"location":"os/core_os/event_queue/os_eventq_designate/#arguments","text":"Arguments Description cur_evq Current event queue pointer to reassign new_evq New event queue to use for the package start_ev Start event to add to the new event queue","title":"Arguments"},{"location":"os/core_os/event_queue/os_eventq_designate/#returned-values","text":"None","title":"Returned values"},{"location":"os/core_os/event_queue/os_eventq_designate/#notes","text":"","title":"Notes"},{"location":"os/core_os/event_queue/os_eventq_designate/#example","text":"This example shows the mgmt_evq_set() function that the mgmt/newtmgr package implements. The function allows an application to specify an event queue for newtmgr to use. The mgmt_evq_set() function calls the os_eventq_designate() function to reassign the nmgr_evq to the event queue that the application specifies. void mgmt_evq_set ( struct os_eventq *evq ) { os_eventq_designate ( &nmgr_evq , evq , NULL ); }","title":"Example"},{"location":"os/core_os/event_queue/os_eventq_dflt_get/","text":"os_eventq_dflt_get struct os_eventq *os_eventq_dflt_get ( void ) Gets the OS default event queue that Mynewt creates at startup. Arguments None Returned values struct os_eventq * : Pointer to OS the default event queue. Notes None Example This example shows an application's main() function processing events from the OS default event queue. void main ( int argc , char **argv ) { sysinit (); ... while ( 1 ) { os_eventq_run ( os_eventq_dflt_get ()); } }","title":"os_eventq_dflt_get"},{"location":"os/core_os/event_queue/os_eventq_dflt_get/#os_eventq_dflt_get","text":"struct os_eventq *os_eventq_dflt_get ( void ) Gets the OS default event queue that Mynewt creates at startup.","title":" os_eventq_dflt_get"},{"location":"os/core_os/event_queue/os_eventq_dflt_get/#arguments","text":"None","title":"Arguments"},{"location":"os/core_os/event_queue/os_eventq_dflt_get/#returned-values","text":"struct os_eventq * : Pointer to OS the default event queue.","title":"Returned values"},{"location":"os/core_os/event_queue/os_eventq_dflt_get/#notes","text":"None","title":"Notes"},{"location":"os/core_os/event_queue/os_eventq_dflt_get/#example","text":"This example shows an application's main() function processing events from the OS default event queue. void main ( int argc , char **argv ) { sysinit (); ... while ( 1 ) { os_eventq_run ( os_eventq_dflt_get ()); } }","title":"Example"},{"location":"os/core_os/event_queue/os_eventq_dflt_set/","text":"os_eventq_dflt_set void os_eventq_dflt_set ( struct os_eventq *evq ) Sets struct os_eventq as the default event queue Arguments Arguments Description evq Pointer to default event queue to use Returned values None Notes Usually done at subsystem init time; before OS has been started, and before interrupts generating events have been enabled. Example This sets the default event queue used by newtmgr task. struct os_eventq g_nmgr_evq ; int nmgr_task_init ( uint8_t prio , os_stack_t *stack_ptr , uint16_t stack_len ) { /* variable declarations here */ os_eventq_init ( &g_nmgr_evq ); os_eventq_dflt_set ( &g_nmgr_evq ); /* initialization continues here */ }","title":"Os eventq dflt set"},{"location":"os/core_os/event_queue/os_eventq_dflt_set/#os_eventq_dflt_set","text":"void os_eventq_dflt_set ( struct os_eventq *evq ) Sets struct os_eventq as the default event queue","title":" os_eventq_dflt_set"},{"location":"os/core_os/event_queue/os_eventq_dflt_set/#arguments","text":"Arguments Description evq Pointer to default event queue to use","title":"Arguments"},{"location":"os/core_os/event_queue/os_eventq_dflt_set/#returned-values","text":"None","title":"Returned values"},{"location":"os/core_os/event_queue/os_eventq_dflt_set/#notes","text":"Usually done at subsystem init time; before OS has been started, and before interrupts generating events have been enabled.","title":"Notes"},{"location":"os/core_os/event_queue/os_eventq_dflt_set/#example","text":"This sets the default event queue used by newtmgr task. struct os_eventq g_nmgr_evq ; int nmgr_task_init ( uint8_t prio , os_stack_t *stack_ptr , uint16_t stack_len ) { /* variable declarations here */ os_eventq_init ( &g_nmgr_evq ); os_eventq_dflt_set ( &g_nmgr_evq ); /* initialization continues here */ }","title":"Example"},{"location":"os/core_os/event_queue/os_eventq_get/","text":"os_eventq_get struct os_event * os_eventq_get ( struct os_eventq *evq ) Dequeues and returns an event from the head of an event queue. When the event queue is empty, the function puts the task into the sleeping state. Arguments Arguments Description evq Event queue to retrieve the event from Returned values A pointer to the os_event structure for the event dequeued from the queue. Notes In most cases, you do not need to call this function directly. You should call the os_eventq_run() wrapper function that calls this function to retrieve an event and then calls the callback function to process the event. Example Example of the os_eventq_run() wrapper function that calls this function: void os_eventq_run ( struct os_eventq *evq ) { struct os_event *ev ; ev = os_eventq_get ( evq ); assert ( ev->ev_cb != NULL ); ev->ev_cb ( ev ); }","title":"os_eventq_get"},{"location":"os/core_os/event_queue/os_eventq_get/#os_eventq_get","text":"struct os_event * os_eventq_get ( struct os_eventq *evq ) Dequeues and returns an event from the head of an event queue. When the event queue is empty, the function puts the task into the sleeping state.","title":" os_eventq_get"},{"location":"os/core_os/event_queue/os_eventq_get/#arguments","text":"Arguments Description evq Event queue to retrieve the event from","title":"Arguments"},{"location":"os/core_os/event_queue/os_eventq_get/#returned-values","text":"A pointer to the os_event structure for the event dequeued from the queue.","title":"Returned values"},{"location":"os/core_os/event_queue/os_eventq_get/#notes","text":"In most cases, you do not need to call this function directly. You should call the os_eventq_run() wrapper function that calls this function to retrieve an event and then calls the callback function to process the event.","title":"Notes"},{"location":"os/core_os/event_queue/os_eventq_get/#example","text":"Example of the os_eventq_run() wrapper function that calls this function: void os_eventq_run ( struct os_eventq *evq ) { struct os_event *ev ; ev = os_eventq_get ( evq ); assert ( ev->ev_cb != NULL ); ev->ev_cb ( ev ); }","title":"Example"},{"location":"os/core_os/event_queue/os_eventq_init/","text":"os_eventq_init void os_eventq_init ( struct os_eventq *evq ) Initializes an event queue. Arguments Arguments Description evq Pointer to the event queue to initialize Returned values None Notes Called during OS, package, and application initialization and before interrupts generating events have been enabled. Example This example shows the app/bletest application initializing the g_bletest_evq event queue. struct os_eventq g_bletest_evq ; int main ( void ) { /* variable declarations here */ os_eventq_init ( &g_bletest_evq ); /* initialization continues here */ }","title":"os_eventq_init"},{"location":"os/core_os/event_queue/os_eventq_init/#os_eventq_init","text":"void os_eventq_init ( struct os_eventq *evq ) Initializes an event queue.","title":" os_eventq_init"},{"location":"os/core_os/event_queue/os_eventq_init/#arguments","text":"Arguments Description evq Pointer to the event queue to initialize","title":"Arguments"},{"location":"os/core_os/event_queue/os_eventq_init/#returned-values","text":"None","title":"Returned values"},{"location":"os/core_os/event_queue/os_eventq_init/#notes","text":"Called during OS, package, and application initialization and before interrupts generating events have been enabled.","title":"Notes"},{"location":"os/core_os/event_queue/os_eventq_init/#example","text":"This example shows the app/bletest application initializing the g_bletest_evq event queue. struct os_eventq g_bletest_evq ; int main ( void ) { /* variable declarations here */ os_eventq_init ( &g_bletest_evq ); /* initialization continues here */ }","title":"Example"},{"location":"os/core_os/event_queue/os_eventq_inited/","text":"os_eventq_inited int os_eventq_inited ( const struct os_eventq *evq ) Indicates whether an event queue has been initialized. Arguments Arguments Description evq Pointer to the event queue to check Returned values 1 if the event queue has been initialized and ready for use. 0 if the event queue has not been initialized. Notes You do not need to call this function prior to using an event queue if you have called the os_eventq_init() function to initialize the queue. Example This example checks whether an event queue has been initialized. struct os_eventq g_my_evq ; int my_task_init ( uint8_t prio , os_stack_t *stack_ptr , uint16_t stack_len ) { /* variable declarations here */ if ( os_eventq_inited ( &g_my_evq )) { /* deal with the event queue */ }; }","title":"os_eventq_inited"},{"location":"os/core_os/event_queue/os_eventq_inited/#os_eventq_inited","text":"int os_eventq_inited ( const struct os_eventq *evq ) Indicates whether an event queue has been initialized.","title":" os_eventq_inited"},{"location":"os/core_os/event_queue/os_eventq_inited/#arguments","text":"Arguments Description evq Pointer to the event queue to check","title":"Arguments"},{"location":"os/core_os/event_queue/os_eventq_inited/#returned-values","text":"1 if the event queue has been initialized and ready for use. 0 if the event queue has not been initialized.","title":"Returned values"},{"location":"os/core_os/event_queue/os_eventq_inited/#notes","text":"You do not need to call this function prior to using an event queue if you have called the os_eventq_init() function to initialize the queue.","title":"Notes"},{"location":"os/core_os/event_queue/os_eventq_inited/#example","text":"This example checks whether an event queue has been initialized. struct os_eventq g_my_evq ; int my_task_init ( uint8_t prio , os_stack_t *stack_ptr , uint16_t stack_len ) { /* variable declarations here */ if ( os_eventq_inited ( &g_my_evq )) { /* deal with the event queue */ }; }","title":"Example"},{"location":"os/core_os/event_queue/os_eventq_put/","text":"os_eventq_put void os_eventq_put ( struct os_eventq *evq , struct os_event *ev ) Enqueues an event onto the tail of an event queue. It puts a task, if any, that is in the sleeping state waiting for an event into the ready-to-run state. Arguments Arguments Description evq Event queue to add the event to ev Event to enqueue Returned values N/A Example This example shows the ble host adding a host controller interface event to the ble_hs_eventq event queue. /* Returns the ble_hs_eventq */ static struct os_eventq * ble_hs_evq_get ( void ) { return ble_hs_evq ; } /* Event callback function */ static void ble_hs_event_rx_hci_ev ( struct os_event *ev ) { uint8_t *hci_evt ; int rc ; hci_evt = ev->ev_arg ; rc = os_memblock_put ( &ble_hs_hci_ev_pool , ev ); BLE_HS_DBG_ASSERT_EVAL ( rc == 0 ); ble_hs_hci_evt_process ( hci_evt ); } void ble_hs_enqueue_hci_event ( uint8_t *hci_evt ) { struct os_event *ev ; /* Allocates memory for the event */ ev = os_memblock_get ( &ble_hs_hci_ev_pool ); if ( ev == NULL ) { ble_hci_trans_buf_free ( hci_evt ); } else { /* * Initializes the event with the ble_hs_event_rx_hci_ev callback function * and the hci_evt data for the callback function to use. */ ev->ev_queued = 0 ; ev->ev_cb = ble_hs_event_rx_hci_ev ; ev->ev_arg = hci_evt ; /* Enqueues the event on the ble_hs_evq */ os_eventq_put ( ble_hs_evq_get (), ev ); } }","title":"os_eventq_put"},{"location":"os/core_os/event_queue/os_eventq_put/#os_eventq_put","text":"void os_eventq_put ( struct os_eventq *evq , struct os_event *ev ) Enqueues an event onto the tail of an event queue. It puts a task, if any, that is in the sleeping state waiting for an event into the ready-to-run state.","title":" os_eventq_put"},{"location":"os/core_os/event_queue/os_eventq_put/#arguments","text":"Arguments Description evq Event queue to add the event to ev Event to enqueue","title":"Arguments"},{"location":"os/core_os/event_queue/os_eventq_put/#returned-values","text":"N/A","title":"Returned values"},{"location":"os/core_os/event_queue/os_eventq_put/#example","text":"This example shows the ble host adding a host controller interface event to the ble_hs_eventq event queue. /* Returns the ble_hs_eventq */ static struct os_eventq * ble_hs_evq_get ( void ) { return ble_hs_evq ; } /* Event callback function */ static void ble_hs_event_rx_hci_ev ( struct os_event *ev ) { uint8_t *hci_evt ; int rc ; hci_evt = ev->ev_arg ; rc = os_memblock_put ( &ble_hs_hci_ev_pool , ev ); BLE_HS_DBG_ASSERT_EVAL ( rc == 0 ); ble_hs_hci_evt_process ( hci_evt ); } void ble_hs_enqueue_hci_event ( uint8_t *hci_evt ) { struct os_event *ev ; /* Allocates memory for the event */ ev = os_memblock_get ( &ble_hs_hci_ev_pool ); if ( ev == NULL ) { ble_hci_trans_buf_free ( hci_evt ); } else { /* * Initializes the event with the ble_hs_event_rx_hci_ev callback function * and the hci_evt data for the callback function to use. */ ev->ev_queued = 0 ; ev->ev_cb = ble_hs_event_rx_hci_ev ; ev->ev_arg = hci_evt ; /* Enqueues the event on the ble_hs_evq */ os_eventq_put ( ble_hs_evq_get (), ev ); } }","title":"Example"},{"location":"os/core_os/event_queue/os_eventq_remove/","text":"os_eventq_remove void os_eventq_remove ( struct os_eventq *evq , struct os_event *ev ) Removes an event from an event queue. Arguments Arguments Description evq Event queue to remove the event from ev Event to remove Returned values N/A Notes Example This example from the os_callout_stop() function shows how to remove a callout event from an event queue. It removes the event from the queue if the event is queued. void os_callout_stop ( struct os_callout *c ) { os_sr_t sr ; OS_ENTER_CRITICAL ( sr ); if ( os_callout_queued ( c )) { TAILQ_REMOVE ( &g_callout_list , c , c_next ); c->c_next . tqe_prev = NULL ; } if ( c->c_evq ) { os_eventq_remove ( c->c_evq , &c->c_ev ); } OS_EXIT_CRITICAL ( sr ); }","title":"os_eventq_remove"},{"location":"os/core_os/event_queue/os_eventq_remove/#os_eventq_remove","text":"void os_eventq_remove ( struct os_eventq *evq , struct os_event *ev ) Removes an event from an event queue.","title":" os_eventq_remove"},{"location":"os/core_os/event_queue/os_eventq_remove/#arguments","text":"Arguments Description evq Event queue to remove the event from ev Event to remove","title":"Arguments"},{"location":"os/core_os/event_queue/os_eventq_remove/#returned-values","text":"N/A","title":"Returned values"},{"location":"os/core_os/event_queue/os_eventq_remove/#notes","text":"","title":"Notes"},{"location":"os/core_os/event_queue/os_eventq_remove/#example","text":"This example from the os_callout_stop() function shows how to remove a callout event from an event queue. It removes the event from the queue if the event is queued. void os_callout_stop ( struct os_callout *c ) { os_sr_t sr ; OS_ENTER_CRITICAL ( sr ); if ( os_callout_queued ( c )) { TAILQ_REMOVE ( &g_callout_list , c , c_next ); c->c_next . tqe_prev = NULL ; } if ( c->c_evq ) { os_eventq_remove ( c->c_evq , &c->c_ev ); } OS_EXIT_CRITICAL ( sr ); }","title":"Example"},{"location":"os/core_os/event_queue/os_eventq_run/","text":"os_eventq_run void os_eventq_run ( struct os_eventq *evq ) Wrapper function that calls the os_eventq_get() function to dequeue the event from the head of the event queue and then calls the callback function for the event. Arguments Arguments Description evq Event queue to dequeue the event from Returned values None Notes Example This example shows an application main() that calls the os_eventq_run() function to process events from the OS default event queue in an infinite loop. int main ( int argc , char **argv ) { sysinit (); ... while ( 1 ) { os_eventq_run ( os_eventq_dflt_get ()); } }","title":"os_eventq_run"},{"location":"os/core_os/event_queue/os_eventq_run/#os_eventq_run","text":"void os_eventq_run ( struct os_eventq *evq ) Wrapper function that calls the os_eventq_get() function to dequeue the event from the head of the event queue and then calls the callback function for the event.","title":" os_eventq_run"},{"location":"os/core_os/event_queue/os_eventq_run/#arguments","text":"Arguments Description evq Event queue to dequeue the event from","title":"Arguments"},{"location":"os/core_os/event_queue/os_eventq_run/#returned-values","text":"None","title":"Returned values"},{"location":"os/core_os/event_queue/os_eventq_run/#notes","text":"","title":"Notes"},{"location":"os/core_os/event_queue/os_eventq_run/#example","text":"This example shows an application main() that calls the os_eventq_run() function to process events from the OS default event queue in an infinite loop. int main ( int argc , char **argv ) { sysinit (); ... while ( 1 ) { os_eventq_run ( os_eventq_dflt_get ()); } }","title":"Example"},{"location":"os/core_os/heap/heap/","text":"Heap API for doing dynamic memory allocation. Description This provides malloc() & free() functionality with locking. The shared resource heap needs to be protected from concurrent access when OS has been started. os_malloc() function grabs a mutex before calling malloc() . Data structures N/A List of Functions The functions available in heap are: Function Description os_free Frees previously allocated memory back to the heap. os_malloc Allocates the given number of bytes from heap and returns a pointer to it. os_realloc Tries to resize previously allocated memory block, and returns pointer to resized memory.","title":"toc"},{"location":"os/core_os/heap/heap/#heap","text":"API for doing dynamic memory allocation.","title":"Heap"},{"location":"os/core_os/heap/heap/#description","text":"This provides malloc() & free() functionality with locking. The shared resource heap needs to be protected from concurrent access when OS has been started. os_malloc() function grabs a mutex before calling malloc() .","title":"Description"},{"location":"os/core_os/heap/heap/#data-structures","text":"N/A","title":"Data structures"},{"location":"os/core_os/heap/heap/#list-of-functions","text":"The functions available in heap are: Function Description os_free Frees previously allocated memory back to the heap. os_malloc Allocates the given number of bytes from heap and returns a pointer to it. os_realloc Tries to resize previously allocated memory block, and returns pointer to resized memory.","title":"List of Functions"},{"location":"os/core_os/heap/os_free/","text":"os_free void os_free ( void *mem ) Frees previously allocated memory back to the heap. Arguments Arguments Description mem Pointer to memory being released Returned values N/A Notes Calls C-library free() under the covers. Example os_free ( info );","title":"os_free"},{"location":"os/core_os/heap/os_free/#os_free","text":"void os_free ( void *mem ) Frees previously allocated memory back to the heap.","title":"os_free"},{"location":"os/core_os/heap/os_free/#arguments","text":"Arguments Description mem Pointer to memory being released","title":"Arguments"},{"location":"os/core_os/heap/os_free/#returned-values","text":"N/A","title":"Returned values"},{"location":"os/core_os/heap/os_free/#notes","text":"Calls C-library free() under the covers.","title":"Notes"},{"location":"os/core_os/heap/os_free/#example","text":"os_free ( info );","title":"Example"},{"location":"os/core_os/heap/os_malloc/","text":"os_malloc void *os_malloc ( size_t size ) Allocates size number of bytes from heap and returns a pointer to it. Arguments Arguments Description size Number of bytes to allocate Returned values <ptr> : pointer to memory allocated from heap. NULL : not enough memory available. Notes os_malloc() calls malloc() , which is provided by the C-library. The heap must be set up during platform initialization. Depending on which C-library you use, you might have to do the heap setup differently. Most often malloc() implementation will maintain a list of allocated and then freed memory blocks. If user asks for memory which cannot be satisfied from free list, they'll call platform's sbrk() , which then tries to grow the heap. Example info = ( struct os_task_info * ) os_malloc ( sizeof ( struct os_task_info ) * tcount ); if ( !info ) { rc = -1 ; goto err ; }","title":"os_malloc"},{"location":"os/core_os/heap/os_malloc/#os_malloc","text":"void *os_malloc ( size_t size ) Allocates size number of bytes from heap and returns a pointer to it.","title":" os_malloc"},{"location":"os/core_os/heap/os_malloc/#arguments","text":"Arguments Description size Number of bytes to allocate","title":"Arguments"},{"location":"os/core_os/heap/os_malloc/#returned-values","text":"<ptr> : pointer to memory allocated from heap. NULL : not enough memory available.","title":"Returned values"},{"location":"os/core_os/heap/os_malloc/#notes","text":"os_malloc() calls malloc() , which is provided by the C-library. The heap must be set up during platform initialization. Depending on which C-library you use, you might have to do the heap setup differently. Most often malloc() implementation will maintain a list of allocated and then freed memory blocks. If user asks for memory which cannot be satisfied from free list, they'll call platform's sbrk() , which then tries to grow the heap.","title":"Notes"},{"location":"os/core_os/heap/os_malloc/#example","text":"info = ( struct os_task_info * ) os_malloc ( sizeof ( struct os_task_info ) * tcount ); if ( !info ) { rc = -1 ; goto err ; }","title":"Example"},{"location":"os/core_os/heap/os_realloc/","text":"os_realloc void *os_realloc ( void *ptr , size_t size ) Tries to resize previously allocated memory block, and returns pointer to resized memory. ptr can be NULL , in which case the call is similar to calling os_malloc() . Arguments Arguments Description ptr Pointer to previously allocated memory size New size to adjust the memory block to Returned values NULL : size adjustment was not successful. ptr : pointer to new start of memory block Notes Example <Insert the code snippet here>","title":"os_realloc"},{"location":"os/core_os/heap/os_realloc/#os_realloc","text":"void *os_realloc ( void *ptr , size_t size ) Tries to resize previously allocated memory block, and returns pointer to resized memory. ptr can be NULL , in which case the call is similar to calling os_malloc() .","title":"os_realloc"},{"location":"os/core_os/heap/os_realloc/#arguments","text":"Arguments Description ptr Pointer to previously allocated memory size New size to adjust the memory block to","title":"Arguments"},{"location":"os/core_os/heap/os_realloc/#returned-values","text":"NULL : size adjustment was not successful. ptr : pointer to new start of memory block","title":"Returned values"},{"location":"os/core_os/heap/os_realloc/#notes","text":"","title":"Notes"},{"location":"os/core_os/heap/os_realloc/#example","text":"<Insert the code snippet here>","title":"Example"},{"location":"os/core_os/mbuf/OS_MBUF_DATA/","text":"OS_MBUF_DATA OS_MBUF_DATA ( __om , __type ) Macro used to cast the data pointer of an mbuf to a given type. Arguments Arguments Description __om Pointer to mbuf (struct os_mbuf *) __type Type to cast Example struct os_mbuf *om uint8_t *rxbuf ; rxbuf = OS_MBUF_DATA ( om , uint8_t * );","title":"OS_MBUF_DATA"},{"location":"os/core_os/mbuf/OS_MBUF_DATA/#os_mbuf_data","text":"OS_MBUF_DATA ( __om , __type ) Macro used to cast the data pointer of an mbuf to a given type.","title":"OS_MBUF_DATA"},{"location":"os/core_os/mbuf/OS_MBUF_DATA/#arguments","text":"Arguments Description __om Pointer to mbuf (struct os_mbuf *) __type Type to cast","title":"Arguments"},{"location":"os/core_os/mbuf/OS_MBUF_DATA/#example","text":"struct os_mbuf *om uint8_t *rxbuf ; rxbuf = OS_MBUF_DATA ( om , uint8_t * );","title":"Example"},{"location":"os/core_os/mbuf/OS_MBUF_LEADINGSPACE/","text":"OS_MBUF_LEADINGSPACE OS_MBUF_LEADINGSPACE ( __om ) Macro used to get the amount of leading space in an mbuf (in bytes). Arguments Arguments Description __om Pointer to mbuf (struct os_mbuf *) Notes This macro works on both normal mbufs and packet header mbufs. The amount of leading space is the number of bytes between the current om_data pointer of the mbuf and the start of the mbuf user data buffer. Example uint8_t *dptr ; uint16_t space ; struct os_mbuf *om ; struct my_data_struct my_data ; /* Copy data from \"my_data\" into the start of an mbuf but only if there is enough room */ space = OS_MBUF_LEADINGSPACE ( om ); if ( space >= sizeof ( struct my_data_struct )) { dptr = om->om_data - sizeof ( struct my_data_struct ); memcpy ( dptr , &my_data , sizeof ( struct my_data_struct )); }","title":"OS_MBUF_LEADINGSPACE"},{"location":"os/core_os/mbuf/OS_MBUF_LEADINGSPACE/#os_mbuf_leadingspace","text":"OS_MBUF_LEADINGSPACE ( __om ) Macro used to get the amount of leading space in an mbuf (in bytes).","title":"OS_MBUF_LEADINGSPACE"},{"location":"os/core_os/mbuf/OS_MBUF_LEADINGSPACE/#arguments","text":"Arguments Description __om Pointer to mbuf (struct os_mbuf *)","title":"Arguments"},{"location":"os/core_os/mbuf/OS_MBUF_LEADINGSPACE/#notes","text":"This macro works on both normal mbufs and packet header mbufs. The amount of leading space is the number of bytes between the current om_data pointer of the mbuf and the start of the mbuf user data buffer.","title":"Notes"},{"location":"os/core_os/mbuf/OS_MBUF_LEADINGSPACE/#example","text":"uint8_t *dptr ; uint16_t space ; struct os_mbuf *om ; struct my_data_struct my_data ; /* Copy data from \"my_data\" into the start of an mbuf but only if there is enough room */ space = OS_MBUF_LEADINGSPACE ( om ); if ( space >= sizeof ( struct my_data_struct )) { dptr = om->om_data - sizeof ( struct my_data_struct ); memcpy ( dptr , &my_data , sizeof ( struct my_data_struct )); }","title":"Example"},{"location":"os/core_os/mbuf/OS_MBUF_PKTHDR/","text":"OS_MBUF_PKTHDR OS_MBUF_PKTHDR ( __om ) Macro used to get a pointer to the os mbuf packet header of an mbuf. Arguments Arguments Description __om Pointer to mbuf (struct os_mbuf *) Example int does_packet_have_data ( struct os_mbuf *om ) { struct os_mbuf_pkthdr *hdr ; hdr = OS_MBUF_PKTHDR ( om ); if ( hdr->omp_len != 0 ) { /* Packet has data in it */ return TRUE } else { /* Packet has no data */ return FALSE ; } }","title":"OS_MBUF_PKTHDR"},{"location":"os/core_os/mbuf/OS_MBUF_PKTHDR/#os_mbuf_pkthdr","text":"OS_MBUF_PKTHDR ( __om ) Macro used to get a pointer to the os mbuf packet header of an mbuf.","title":"OS_MBUF_PKTHDR"},{"location":"os/core_os/mbuf/OS_MBUF_PKTHDR/#arguments","text":"Arguments Description __om Pointer to mbuf (struct os_mbuf *)","title":"Arguments"},{"location":"os/core_os/mbuf/OS_MBUF_PKTHDR/#example","text":"int does_packet_have_data ( struct os_mbuf *om ) { struct os_mbuf_pkthdr *hdr ; hdr = OS_MBUF_PKTHDR ( om ); if ( hdr->omp_len != 0 ) { /* Packet has data in it */ return TRUE } else { /* Packet has no data */ return FALSE ; } }","title":"Example"},{"location":"os/core_os/mbuf/OS_MBUF_PKTHDR_TO_MBUF/","text":"OS_MBUF_PKTHDR_TO_MBUF OS_MBUF_PKTHDR_TO_MBUF ( __hdr ) Macro used to get a pointer to the mbuf given a pointer to the os mbuf packet header Arguments Arguments Description __hdr Pointer to os mbuf packet header (struct os_mbuf_pkthdr *) Example struct os_mbuf *om ; struct os_mbuf_pkthdr *hdr ; om = OS_MBUF_PKTHDR_TO_MBUF ( hdr ); os_mbuf_free_chain ( om );","title":"OS_MBUF_PKTHDR_TO_MBUF"},{"location":"os/core_os/mbuf/OS_MBUF_PKTHDR_TO_MBUF/#os_mbuf_pkthdr_to_mbuf","text":"OS_MBUF_PKTHDR_TO_MBUF ( __hdr ) Macro used to get a pointer to the mbuf given a pointer to the os mbuf packet header","title":"OS_MBUF_PKTHDR_TO_MBUF"},{"location":"os/core_os/mbuf/OS_MBUF_PKTHDR_TO_MBUF/#arguments","text":"Arguments Description __hdr Pointer to os mbuf packet header (struct os_mbuf_pkthdr *)","title":"Arguments"},{"location":"os/core_os/mbuf/OS_MBUF_PKTHDR_TO_MBUF/#example","text":"struct os_mbuf *om ; struct os_mbuf_pkthdr *hdr ; om = OS_MBUF_PKTHDR_TO_MBUF ( hdr ); os_mbuf_free_chain ( om );","title":"Example"},{"location":"os/core_os/mbuf/OS_MBUF_PKTLEN/","text":"OS_MBUF_PKTLEN OS_MBUF_PKTLEN ( __om ) Macro used to get the length of an entire mbuf chain. Arguments Arguments Description __om Pointer to mbuf (struct os_mbuf *) Example uint16_t pktlen ; struct os_mbuf *om ; /* Check if there is any data in the mbuf chain */ pktlen = OS_MBUF_PKTLEN ( om ); if ( pktlen != 0 ) { /* mbuf chain has data */ }","title":"OS_MBUF_PKTLEN"},{"location":"os/core_os/mbuf/OS_MBUF_PKTLEN/#os_mbuf_pktlen","text":"OS_MBUF_PKTLEN ( __om ) Macro used to get the length of an entire mbuf chain.","title":"OS_MBUF_PKTLEN"},{"location":"os/core_os/mbuf/OS_MBUF_PKTLEN/#arguments","text":"Arguments Description __om Pointer to mbuf (struct os_mbuf *)","title":"Arguments"},{"location":"os/core_os/mbuf/OS_MBUF_PKTLEN/#example","text":"uint16_t pktlen ; struct os_mbuf *om ; /* Check if there is any data in the mbuf chain */ pktlen = OS_MBUF_PKTLEN ( om ); if ( pktlen != 0 ) { /* mbuf chain has data */ }","title":"Example"},{"location":"os/core_os/mbuf/OS_MBUF_TRAILINGSPACE/","text":"OS_MBUF_TRAILINGSPACE OS_MBUF_TRAILINGSPACE ( __om ) Macro used to get the amount of trailing space in an mbuf (in bytes). Arguments Arguments Description __om Pointer to mbuf (struct os_mbuf *) Notes This macro works on both normal mbufs and packet header mbufs. The amount of trailing space is the number of bytes between the current om_data pointer of the mbuf and the end of the mbuf. Example uint16_t space ; struct os_mbuf *om ; struct my_data_struct my_data ; /* Copy data from \"my_data\" to the end of an mbuf but only if there is enough room */ space = OS_MBUF_TRAILINGSPACE ( om ); if ( space >= sizeof ( struct my_data_struct )) { memcpy ( om->om_data , &my_data , sizeof ( struct my_data_struct )); }","title":"OS_MBUF_TRAILINGSPACE"},{"location":"os/core_os/mbuf/OS_MBUF_TRAILINGSPACE/#os_mbuf_trailingspace","text":"OS_MBUF_TRAILINGSPACE ( __om ) Macro used to get the amount of trailing space in an mbuf (in bytes).","title":"OS_MBUF_TRAILINGSPACE"},{"location":"os/core_os/mbuf/OS_MBUF_TRAILINGSPACE/#arguments","text":"Arguments Description __om Pointer to mbuf (struct os_mbuf *)","title":"Arguments"},{"location":"os/core_os/mbuf/OS_MBUF_TRAILINGSPACE/#notes","text":"This macro works on both normal mbufs and packet header mbufs. The amount of trailing space is the number of bytes between the current om_data pointer of the mbuf and the end of the mbuf.","title":"Notes"},{"location":"os/core_os/mbuf/OS_MBUF_TRAILINGSPACE/#example","text":"uint16_t space ; struct os_mbuf *om ; struct my_data_struct my_data ; /* Copy data from \"my_data\" to the end of an mbuf but only if there is enough room */ space = OS_MBUF_TRAILINGSPACE ( om ); if ( space >= sizeof ( struct my_data_struct )) { memcpy ( om->om_data , &my_data , sizeof ( struct my_data_struct )); }","title":"Example"},{"location":"os/core_os/mbuf/OS_MBUF_USRHDR/","text":"OS_MBUF_USRHDR OS_MBUF_USRHDR ( __om ) Macro used to get a pointer to the user packet header of an mbuf. Arguments Arguments Description __om Pointer to mbuf (struct os_mbuf *). Must be head of chain (i.e. a packet header mbuf) Example struct os_mbuf *om struct user_header *hdr ; hdr = OS_MBUF_USRHDR ( om );","title":"OS_MBUF_USRHDR"},{"location":"os/core_os/mbuf/OS_MBUF_USRHDR/#os_mbuf_usrhdr","text":"OS_MBUF_USRHDR ( __om ) Macro used to get a pointer to the user packet header of an mbuf.","title":"OS_MBUF_USRHDR"},{"location":"os/core_os/mbuf/OS_MBUF_USRHDR/#arguments","text":"Arguments Description __om Pointer to mbuf (struct os_mbuf *). Must be head of chain (i.e. a packet header mbuf)","title":"Arguments"},{"location":"os/core_os/mbuf/OS_MBUF_USRHDR/#example","text":"struct os_mbuf *om struct user_header *hdr ; hdr = OS_MBUF_USRHDR ( om );","title":"Example"},{"location":"os/core_os/mbuf/OS_MBUF_USRHDR_LEN/","text":"OS_MBUF_USRHDR_LEN OS_MBUF_USRHDR_LEN ( __om ) Macro used to retrieve the length of the user packet header in an mbuf. Arguments Arguments Description __om Pointer to mbuf (struct os_mbuf *). Must be head of chain (i.e. a packet header mbuf) Example uint16_t user_length ; struct os_mbuf *om struct user_header *hdr ; user_length = OS_MBUF_USRHDR_LEN ( om );","title":"OS_MBUF_USRHDR_LEN"},{"location":"os/core_os/mbuf/OS_MBUF_USRHDR_LEN/#os_mbuf_usrhdr_len","text":"OS_MBUF_USRHDR_LEN ( __om ) Macro used to retrieve the length of the user packet header in an mbuf.","title":"OS_MBUF_USRHDR_LEN"},{"location":"os/core_os/mbuf/OS_MBUF_USRHDR_LEN/#arguments","text":"Arguments Description __om Pointer to mbuf (struct os_mbuf *). Must be head of chain (i.e. a packet header mbuf)","title":"Arguments"},{"location":"os/core_os/mbuf/OS_MBUF_USRHDR_LEN/#example","text":"uint16_t user_length ; struct os_mbuf *om struct user_header *hdr ; user_length = OS_MBUF_USRHDR_LEN ( om );","title":"Example"},{"location":"os/core_os/mbuf/mbuf/","text":"Mbufs The mbuf (short for memory buffer) is a common concept in networking stacks. The mbuf is used to hold packet data as it traverses the stack. The mbuf also generally stores header information or other networking stack information that is carried around with the packet. The mbuf and its associated library of functions were developed to make common networking stack operations (like stripping and adding protocol headers) efficient and as copy-free as possible. In its simplest form, an mbuf is a memory block with some space reserved for internal information and a pointer which is used to \"chain\" memory blocks together in order to create a \"packet\". This is a very important aspect of the mbuf: the ability to chain mbufs together to create larger \"packets\" (chains of mbufs). Why use mbufs? The main reason is to conserve memory. Consider a networking protocol that generally sends small packets but occasionally sends large ones. The Bluetooth Low Energy (BLE) protocol is one such example. A flat buffer would need to be sized so that the maximum packet size could be contained by the buffer. With the mbuf, a number of mbufs can be chained together so that the occasional large packet can be handled while leaving more packet buffers available to the networking stack for smaller packets. Packet Header mbuf Not all mbufs are created equal. The first mbuf in a chain of mbufs is a special mbuf called a \"packet header mbuf\". The reason that this mbuf is special is that it contains the length of all the data contained by the chain of mbufs (the packet length, in other words). The packet header mbuf may also contain a user defined structure (called a \"user header\") so that networking protocol specific information can be conveyed to various layers of the networking stack. Any mbufs that are part of the packet (i.e. in the mbuf chain but not the first one) are \"normal\" (i.e. non-packet header) mbufs. A normal mbuf does not have any packet header or user packet header structures in them; they only contain the basic mbuf header ( struct os_mbuf ). Figure 1 illustrates these two types of mbufs. Note that the numbers/text in parentheses denote the size of the structures/elements (in bytes) and that MBLEN is the memory block length of the memory pool used by the mbuf pool. Normal mbuf Now let's take a deeper dive into the mbuf structure. Figure 2 illustrates a normal mbuf and breaks out the various fields in the os_mbuf structure. The om_data field is a pointer to where the data starts inside the data buffer. Typically, mbufs that are allocated from the mbuf pool (discussed later) have their om_data pointer set to the start of the data buffer but there are cases where this may not be desirable (added a protocol header to a packet, for example). The om_flags field is a set of flags used internally by the mbuf library. Currently, no flags have been defined. The om_pkthdr_len field is the total length of all packet headers in the mbuf. For normal mbufs this is set to 0 as there is no packet or user packet headers. For packet header mbufs, this would be set to the length of the packet header structure (16) plus the size of the user packet header (if any). Note that it is this field which differentiates packet header mbufs from normal mbufs (i.e. if om_pkthdr_len is zero, this is a normal mbuf; otherwise it is a packet header mbuf). The om_len field contains the amount of user data in the data buffer. When initially allocated, this field is 0 as there is no user data in the mbuf. The omp_pool field is a pointer to the pool from which this mbuf has been allocated. This is used internally by the mbuf library. The omp_next field is a linked list element which is used to chain mbufs. Figure 2 also shows a normal mbuf with actual values in the os_mbuf structure. This mbuf starts at address 0x1000 and is 256 bytes in total length. In this example, the user has copied 33 bytes into the data buffer starting at address 0x1010 (this is where om_data points). Note that the packet header length in this mbuf is 0 as it is not a packet header mbuf. Figure 3 illustrates the packet header mbuf along with some chained mbufs (i.e a \"packet\"). In this example, the user header structure is defined to be 8 bytes. Note that in figure 3 we show a number of different mbufs with varying om_data pointers and lengths since we want to show various examples of valid mbufs. For all the mbufs (both packet header and normal ones) the total length of the memory block is 128 bytes. Mbuf pools Mbufs are collected into \"mbuf pools\" much like memory blocks. The mbuf pool itself contains a pointer to a memory pool. The memory blocks in this memory pool are the actual mbufs; both normal and packet header mbufs. Thus, the memory block (and corresponding memory pool) must be sized correctly. In other words, the memory blocks which make up the memory pool used by the mbuf pool must be at least: sizeof(struct os_mbuf) + sizeof(struct os_mbuf_pkthdr) + sizeof(struct user_defined_header) + desired minimum data buffer length . For example, if the developer wants mbufs to contain at least 64 bytes of user data and they have a user header of 12 bytes, the size of the memory block would be (at least): 64 + 12 + 16 + 8, or 100 bytes. Yes, this is a fair amount of overhead. However, the flexibility provided by the mbuf library usually outweighs overhead concerns. Create mbuf pool Creating an mbuf pool is fairly simple: create a memory pool and then create the mbuf pool using that memory pool. Once the developer has determined the size of the user data needed per mbuf (this is based on the application/networking stack and is outside the scope of this discussion) and the size of the user header (if any), the memory blocks can be sized. In the example shown below, the application requires 64 bytes of user data per mbuf and also allocates a user header (called struct user_hdr ). Note that we do not show the user header data structure as there really is no need; all we need to do is to account for it when creating the memory pool. In the example, we use the macro MBUF_PKTHDR_OVERHEAD to denote the amount of packet header overhead per mbuf and MBUF_MEMBLOCK_OVERHEAD to denote the total amount of overhead required per memory block. The macro MBUF_BUF_SIZE is used to denote the amount of payload that the application requires (aligned on a 32-bit boundary in this case). All this leads to the total memory block size required, denoted by the macro MBUF_MEMBLOCK_OVERHEAD . #define MBUF_PKTHDR_OVERHEAD sizeof(struct os_mbuf_pkthdr) + sizeof(struct user_hdr) #define MBUF_MEMBLOCK_OVERHEAD sizeof(struct os_mbuf) + MBUF_PKTHDR_OVERHEAD #define MBUF_NUM_MBUFS (32) #define MBUF_PAYLOAD_SIZE (64) #define MBUF_BUF_SIZE OS_ALIGN(MBUF_PAYLOAD_SIZE, 4) #define MBUF_MEMBLOCK_SIZE (MBUF_BUF_SIZE + MBUF_MEMBLOCK_OVERHEAD) #define MBUF_MEMPOOL_SIZE OS_MEMPOOL_SIZE(MBUF_NUM_MBUFS, MBUF_MEMBLOCK_SIZE) struct os_mbuf_pool g_mbuf_pool ; struct os_mempool g_mbuf_mempool ; os_membuf_t g_mbuf_buffer [ MBUF_MEMPOOL_SIZE ]; void create_mbuf_pool ( void ) { int rc ; rc = os_mempool_init ( &g_mbuf_mempool , MBUF_NUM_MBUFS , MBUF_MEMBLOCK_SIZE , &g_mbuf_buffer [ 0 ], \"mbuf_pool\" ); assert ( rc == 0 ); rc = os_mbuf_pool_init ( &g_mbuf_pool , &g_mbuf_mempool , MBUF_MEMBLOCK_SIZE , MBUF_NUM_MBUFS ); assert ( rc == 0 ); } Using mbufs The following examples illustrate typical mbuf usage. There are two basic mbuf allocation API: os_mbuf_get() and os_mbuf_get_pkthdr() . The first API obtains a normal mbuf whereas the latter obtains a packet header mbuf. Typically, application developers use os_mbuf_get_pkthdr() and rarely, if ever, need to call os_mbuf_get() as the rest of the mbuf API (e.g. os_mbuf_append() , os_mbuf_copyinto() , etc.) typically deal with allocating and chaining mbufs. It is recommended to use the provided API to copy data into/out of mbuf chains and/or manipulate mbufs. In example1 , the developer creates a packet and then sends the packet to a networking interface. The code sample also provides an example of copying data out of an mbuf as well as use of the \"pullup\" api (another very common mbuf api). void mbuf_usage_example1 ( uint8_t *mydata , int mydata_length ) { int rc ; struct os_mbuf *om ; /* get a packet header mbuf */ om = os_mbuf_get_pkthdr ( &g_mbuf_pool , sizeof ( struct user_hdr )); if ( om ) { /* * Copy user data into mbuf. NOTE: if mydata_length is greater than the * mbuf payload size (64 bytes using above example), mbufs are allocated * and chained together to accommodate the total packet length. */ rc = os_mbuf_copyinto ( om , 0 , mydata , len ); if ( rc ) { /* Error! Could not allocate enough mbufs for total packet length */ return -1 ; } /* Send packet to networking interface */ send_pkt ( om ); } } In example2 we show use of the pullup api as this illustrates some of the typical pitfalls developers encounter when using mbufs. The first pitfall is one of alignment/padding. Depending on the processor and/or compiler, the sizeof() a structure may vary. Thus, the size of my_protocol_header may be different inside the packet data of the mbuf than the size of the structure on the stack or as a global variable, for instance. While some networking protcols may align protocol information on convenient processor boundaries many others try to conserve bytes \"on the air\" (i.e inside the packet data). Typical methods used to deal with this are \"packing\" the structure (i.e. force compiler to not pad) or creating protocol headers that do not require padding. example2 assumes that one of these methods was used when defining the my_protocol_header structure. Another common pitfall occurs around endianness. A network protocol may be little endian or big endian; it all depends on the protocol specification. Processors also have an endianness; this means that the developer has to be careful that the processor endianness and the protocol endianness are handled correctly. In example2 , some common networking functions are used: ntohs() and ntohl() . These are shorthand for \"network order to host order, short\" and \"network order to host order, long\". Basically, these functions convert data of a certain size (i.e. 16 bits, 32 bits, etc) to the endianness of the host. Network byte order is big-endian (most significant byte first), so these functions convert big-endian byte order to host order (thus, the implementation of these functions is host dependent). Note that the BLE networking stack \"on the air\" format is least signigicant byte first (i.e. little-endian), so a bletoh function would have to take little-endian format and convert to host format. A long story short: the developer must take care when copying structure data to/from mbufs and flat buffers! A final note: these examples assume the same mbuf struture and definitions used in the first example. void mbuf_usage_example2 ( struct mbuf *rxpkt ) { int rc ; uint8_t packet_data [ 16 ]; struct mbuf *om ; struct my_protocol_header *phdr ; /* Make sure that \"my_protocol_header\" bytes are contiguous in mbuf */ om = os_mbuf_pullup ( &g_mbuf_pool , sizeof ( struct my_protocol_header )); if ( !om ) { /* Not able to pull up data into contiguous area */ return -1 ; } /* * Get the protocol information from the packet. In this example we presume that we * are interested in protocol types that are equal to MY_PROTOCOL_TYPE, are not zero * length, and have had some time in flight. */ phdr = OS_MBUF_DATA ( om , struct my_protocol_header * ); type = ntohs ( phdr->prot_type ); length = ntohs ( phdr->prot_length ); time_in_flight = ntohl ( phdr->prot_tif ); if (( type == MY_PROTOCOL_TYPE ) && ( length > 0 ) && ( time_in_flight > 0 )) { rc = os_mbuf_copydata ( rxpkt , sizeof ( struct my_protocol_header ), 16 , packet_data ); if ( !rc ) { /* Success! Perform operations on packet data */ < ... user code here ... > } } /* Free passed in packet (mbuf chain) since we don't need it anymore */ os_mbuf_free_chain ( om ); } Data Structures struct os_mbuf_pool { uint16_t omp_databuf_len ; uint16_t omp_mbuf_count ; struct os_mempool *omp_pool ; STAILQ_ENTRY ( os_mbuf_pool ) omp_next ; }; Element Description omp_databuf_len The length, in bytes, of the \"data buffer\" of the mbuf. The data buffer of the mbuf is everything except the os_mbuf structure (which is present in all types of mbufs) omp_mbuf_count Total number of mbufs in the pool when allocated. This is NOT the number of free mbufs in the pool! omp_pool The memory pool from which the mbufs are allocated omp_next This is a linked list pointer which chains memory pools. It is used by the system memory pool library struct os_mbuf_pkthdr { uint16_t omp_len ; uint16_t omp_flags ; STAILQ_ENTRY ( os_mbuf_pkthdr ) omp_next ; }; Element Description omp_len Length, in bytes, of the \"packet\". This is the sum of the user data in all the mbufs chained to the packet header mbuf (including the packet header mbuf) omp_flags Packet header flags. omp_next Linked list pointer to chain \"packets\". This can be used to add mbuf chains to a queue or linked list and is there for convenience. struct os_mbuf { uint8_t *om_data ; uint8_t om_flags ; uint8_t om_pkthdr_len ; uint16_t om_len ; struct os_mbuf_pool *om_omp ; SLIST_ENTRY ( os_mbuf ) om_next ; uint8_t om_databuf [ 0 ]; }; Element Description om_data Pointer to start of user data in mbuf data buffer om_flags mbuf flags field. Currently all flags unused. om_pkthdr_len The total length of all packet headers in the mbuf (mbuf packet header plus user packet header), in bytes om_len The length of the user data contained in this mbuf, in bytes om_omp Memory pool pointer. This is the mbuf pool from which this mbuf was allocated. om_next Pointer to next mbuf in packet chain om_databuf mbuf data buffer (accessor to start of mbuf data buffer). Note that the mbuf data buffer refers to the start of either the user data in normal mbufs or the start of the os mbuf packet header for packet header mbufs List of Functions/Macros The functions/macros available in mbuf are: Function/Macro Description OS_MBUF_PKTHDR Get a pointer to the os mbuf packet header of an mbuf. OS_MBUF_PKTHDR_TO_MBUF Get a pointer to the mbuf given a pointer to the os mbuf packet header. OS_MBUF_PKTLEN Get the length of an entire mbuf chain. OS_MBUF_DATA Cast the data pointer of an mbuf to a given type. OS_MBUF_USRHDR Get a pointer to the user packet header of an mbuf. OS_MBUF_USRHDR_LEN Retrieve the length of the user packet header in an mbuf. OS_MBUF_LEADINGSPACE Get the amount of leading space in an mbuf (in bytes). OS_MBUF_TRAILINGSPACE Get the amount of trailing space in an mbuf (in bytes). os_mbuf_adj Trims the given number of bytes from either the head (if positive) or tail (if negative) of an mbuf chain. os_mbuf_append Appends a data buffer of the given length to the end of an mbuf chain. os_mbuf_concat Attaches a second mbuf chain onto the end of the first. os_mbuf_copydata Copy data from an mbuf chain. os_mbuf_copyinto Copies the contents of a flat buffer into an mbuf chain. os_mbuf_dup Duplicate a chain of mbufs. os_mbuf_extend Increases the length of an mbuf chain by the specified amount. os_mbuf_free_chain Frees a chain of mbufs. os_mbuf_get Get an mbuf from the mbuf pool. os_mbuf_get_pkthdr Allocates a packet header mbuf from the given mbuf pool. Adds a user header to the packet header mbuf. os_mbuf_memcmp Performs a memory compare of the specified region of an mbuf chain against a flat buffer. os_mbuf_off Given an offset in the packet, return the mbuf and the offset in that mbuf where byte 'off' is located. os_mbuf_pool_init nitialize an mbuf pool. os_mbuf_prepend Increases the length of an mbuf chain by adding data to the front. os_mbuf_pullup Rearrange an mbuf chain so that the given length of bytes are contiguous and in the data area of an mbuf.","title":"toc"},{"location":"os/core_os/mbuf/mbuf/#mbufs","text":"The mbuf (short for memory buffer) is a common concept in networking stacks. The mbuf is used to hold packet data as it traverses the stack. The mbuf also generally stores header information or other networking stack information that is carried around with the packet. The mbuf and its associated library of functions were developed to make common networking stack operations (like stripping and adding protocol headers) efficient and as copy-free as possible. In its simplest form, an mbuf is a memory block with some space reserved for internal information and a pointer which is used to \"chain\" memory blocks together in order to create a \"packet\". This is a very important aspect of the mbuf: the ability to chain mbufs together to create larger \"packets\" (chains of mbufs).","title":"Mbufs"},{"location":"os/core_os/mbuf/mbuf/#why-use-mbufs","text":"The main reason is to conserve memory. Consider a networking protocol that generally sends small packets but occasionally sends large ones. The Bluetooth Low Energy (BLE) protocol is one such example. A flat buffer would need to be sized so that the maximum packet size could be contained by the buffer. With the mbuf, a number of mbufs can be chained together so that the occasional large packet can be handled while leaving more packet buffers available to the networking stack for smaller packets.","title":"Why use mbufs?"},{"location":"os/core_os/mbuf/mbuf/#packet-header-mbuf","text":"Not all mbufs are created equal. The first mbuf in a chain of mbufs is a special mbuf called a \"packet header mbuf\". The reason that this mbuf is special is that it contains the length of all the data contained by the chain of mbufs (the packet length, in other words). The packet header mbuf may also contain a user defined structure (called a \"user header\") so that networking protocol specific information can be conveyed to various layers of the networking stack. Any mbufs that are part of the packet (i.e. in the mbuf chain but not the first one) are \"normal\" (i.e. non-packet header) mbufs. A normal mbuf does not have any packet header or user packet header structures in them; they only contain the basic mbuf header ( struct os_mbuf ). Figure 1 illustrates these two types of mbufs. Note that the numbers/text in parentheses denote the size of the structures/elements (in bytes) and that MBLEN is the memory block length of the memory pool used by the mbuf pool.","title":"Packet Header mbuf"},{"location":"os/core_os/mbuf/mbuf/#normal-mbuf","text":"Now let's take a deeper dive into the mbuf structure. Figure 2 illustrates a normal mbuf and breaks out the various fields in the os_mbuf structure. The om_data field is a pointer to where the data starts inside the data buffer. Typically, mbufs that are allocated from the mbuf pool (discussed later) have their om_data pointer set to the start of the data buffer but there are cases where this may not be desirable (added a protocol header to a packet, for example). The om_flags field is a set of flags used internally by the mbuf library. Currently, no flags have been defined. The om_pkthdr_len field is the total length of all packet headers in the mbuf. For normal mbufs this is set to 0 as there is no packet or user packet headers. For packet header mbufs, this would be set to the length of the packet header structure (16) plus the size of the user packet header (if any). Note that it is this field which differentiates packet header mbufs from normal mbufs (i.e. if om_pkthdr_len is zero, this is a normal mbuf; otherwise it is a packet header mbuf). The om_len field contains the amount of user data in the data buffer. When initially allocated, this field is 0 as there is no user data in the mbuf. The omp_pool field is a pointer to the pool from which this mbuf has been allocated. This is used internally by the mbuf library. The omp_next field is a linked list element which is used to chain mbufs. Figure 2 also shows a normal mbuf with actual values in the os_mbuf structure. This mbuf starts at address 0x1000 and is 256 bytes in total length. In this example, the user has copied 33 bytes into the data buffer starting at address 0x1010 (this is where om_data points). Note that the packet header length in this mbuf is 0 as it is not a packet header mbuf. Figure 3 illustrates the packet header mbuf along with some chained mbufs (i.e a \"packet\"). In this example, the user header structure is defined to be 8 bytes. Note that in figure 3 we show a number of different mbufs with varying om_data pointers and lengths since we want to show various examples of valid mbufs. For all the mbufs (both packet header and normal ones) the total length of the memory block is 128 bytes.","title":"Normal mbuf"},{"location":"os/core_os/mbuf/mbuf/#mbuf-pools","text":"Mbufs are collected into \"mbuf pools\" much like memory blocks. The mbuf pool itself contains a pointer to a memory pool. The memory blocks in this memory pool are the actual mbufs; both normal and packet header mbufs. Thus, the memory block (and corresponding memory pool) must be sized correctly. In other words, the memory blocks which make up the memory pool used by the mbuf pool must be at least: sizeof(struct os_mbuf) + sizeof(struct os_mbuf_pkthdr) + sizeof(struct user_defined_header) + desired minimum data buffer length . For example, if the developer wants mbufs to contain at least 64 bytes of user data and they have a user header of 12 bytes, the size of the memory block would be (at least): 64 + 12 + 16 + 8, or 100 bytes. Yes, this is a fair amount of overhead. However, the flexibility provided by the mbuf library usually outweighs overhead concerns.","title":"Mbuf pools"},{"location":"os/core_os/mbuf/mbuf/#create-mbuf-pool","text":"Creating an mbuf pool is fairly simple: create a memory pool and then create the mbuf pool using that memory pool. Once the developer has determined the size of the user data needed per mbuf (this is based on the application/networking stack and is outside the scope of this discussion) and the size of the user header (if any), the memory blocks can be sized. In the example shown below, the application requires 64 bytes of user data per mbuf and also allocates a user header (called struct user_hdr ). Note that we do not show the user header data structure as there really is no need; all we need to do is to account for it when creating the memory pool. In the example, we use the macro MBUF_PKTHDR_OVERHEAD to denote the amount of packet header overhead per mbuf and MBUF_MEMBLOCK_OVERHEAD to denote the total amount of overhead required per memory block. The macro MBUF_BUF_SIZE is used to denote the amount of payload that the application requires (aligned on a 32-bit boundary in this case). All this leads to the total memory block size required, denoted by the macro MBUF_MEMBLOCK_OVERHEAD . #define MBUF_PKTHDR_OVERHEAD sizeof(struct os_mbuf_pkthdr) + sizeof(struct user_hdr) #define MBUF_MEMBLOCK_OVERHEAD sizeof(struct os_mbuf) + MBUF_PKTHDR_OVERHEAD #define MBUF_NUM_MBUFS (32) #define MBUF_PAYLOAD_SIZE (64) #define MBUF_BUF_SIZE OS_ALIGN(MBUF_PAYLOAD_SIZE, 4) #define MBUF_MEMBLOCK_SIZE (MBUF_BUF_SIZE + MBUF_MEMBLOCK_OVERHEAD) #define MBUF_MEMPOOL_SIZE OS_MEMPOOL_SIZE(MBUF_NUM_MBUFS, MBUF_MEMBLOCK_SIZE) struct os_mbuf_pool g_mbuf_pool ; struct os_mempool g_mbuf_mempool ; os_membuf_t g_mbuf_buffer [ MBUF_MEMPOOL_SIZE ]; void create_mbuf_pool ( void ) { int rc ; rc = os_mempool_init ( &g_mbuf_mempool , MBUF_NUM_MBUFS , MBUF_MEMBLOCK_SIZE , &g_mbuf_buffer [ 0 ], \"mbuf_pool\" ); assert ( rc == 0 ); rc = os_mbuf_pool_init ( &g_mbuf_pool , &g_mbuf_mempool , MBUF_MEMBLOCK_SIZE , MBUF_NUM_MBUFS ); assert ( rc == 0 ); }","title":"Create mbuf pool"},{"location":"os/core_os/mbuf/mbuf/#using-mbufs","text":"The following examples illustrate typical mbuf usage. There are two basic mbuf allocation API: os_mbuf_get() and os_mbuf_get_pkthdr() . The first API obtains a normal mbuf whereas the latter obtains a packet header mbuf. Typically, application developers use os_mbuf_get_pkthdr() and rarely, if ever, need to call os_mbuf_get() as the rest of the mbuf API (e.g. os_mbuf_append() , os_mbuf_copyinto() , etc.) typically deal with allocating and chaining mbufs. It is recommended to use the provided API to copy data into/out of mbuf chains and/or manipulate mbufs. In example1 , the developer creates a packet and then sends the packet to a networking interface. The code sample also provides an example of copying data out of an mbuf as well as use of the \"pullup\" api (another very common mbuf api). void mbuf_usage_example1 ( uint8_t *mydata , int mydata_length ) { int rc ; struct os_mbuf *om ; /* get a packet header mbuf */ om = os_mbuf_get_pkthdr ( &g_mbuf_pool , sizeof ( struct user_hdr )); if ( om ) { /* * Copy user data into mbuf. NOTE: if mydata_length is greater than the * mbuf payload size (64 bytes using above example), mbufs are allocated * and chained together to accommodate the total packet length. */ rc = os_mbuf_copyinto ( om , 0 , mydata , len ); if ( rc ) { /* Error! Could not allocate enough mbufs for total packet length */ return -1 ; } /* Send packet to networking interface */ send_pkt ( om ); } } In example2 we show use of the pullup api as this illustrates some of the typical pitfalls developers encounter when using mbufs. The first pitfall is one of alignment/padding. Depending on the processor and/or compiler, the sizeof() a structure may vary. Thus, the size of my_protocol_header may be different inside the packet data of the mbuf than the size of the structure on the stack or as a global variable, for instance. While some networking protcols may align protocol information on convenient processor boundaries many others try to conserve bytes \"on the air\" (i.e inside the packet data). Typical methods used to deal with this are \"packing\" the structure (i.e. force compiler to not pad) or creating protocol headers that do not require padding. example2 assumes that one of these methods was used when defining the my_protocol_header structure. Another common pitfall occurs around endianness. A network protocol may be little endian or big endian; it all depends on the protocol specification. Processors also have an endianness; this means that the developer has to be careful that the processor endianness and the protocol endianness are handled correctly. In example2 , some common networking functions are used: ntohs() and ntohl() . These are shorthand for \"network order to host order, short\" and \"network order to host order, long\". Basically, these functions convert data of a certain size (i.e. 16 bits, 32 bits, etc) to the endianness of the host. Network byte order is big-endian (most significant byte first), so these functions convert big-endian byte order to host order (thus, the implementation of these functions is host dependent). Note that the BLE networking stack \"on the air\" format is least signigicant byte first (i.e. little-endian), so a bletoh function would have to take little-endian format and convert to host format. A long story short: the developer must take care when copying structure data to/from mbufs and flat buffers! A final note: these examples assume the same mbuf struture and definitions used in the first example. void mbuf_usage_example2 ( struct mbuf *rxpkt ) { int rc ; uint8_t packet_data [ 16 ]; struct mbuf *om ; struct my_protocol_header *phdr ; /* Make sure that \"my_protocol_header\" bytes are contiguous in mbuf */ om = os_mbuf_pullup ( &g_mbuf_pool , sizeof ( struct my_protocol_header )); if ( !om ) { /* Not able to pull up data into contiguous area */ return -1 ; } /* * Get the protocol information from the packet. In this example we presume that we * are interested in protocol types that are equal to MY_PROTOCOL_TYPE, are not zero * length, and have had some time in flight. */ phdr = OS_MBUF_DATA ( om , struct my_protocol_header * ); type = ntohs ( phdr->prot_type ); length = ntohs ( phdr->prot_length ); time_in_flight = ntohl ( phdr->prot_tif ); if (( type == MY_PROTOCOL_TYPE ) && ( length > 0 ) && ( time_in_flight > 0 )) { rc = os_mbuf_copydata ( rxpkt , sizeof ( struct my_protocol_header ), 16 , packet_data ); if ( !rc ) { /* Success! Perform operations on packet data */ < ... user code here ... > } } /* Free passed in packet (mbuf chain) since we don't need it anymore */ os_mbuf_free_chain ( om ); }","title":"Using mbufs"},{"location":"os/core_os/mbuf/mbuf/#data-structures","text":"struct os_mbuf_pool { uint16_t omp_databuf_len ; uint16_t omp_mbuf_count ; struct os_mempool *omp_pool ; STAILQ_ENTRY ( os_mbuf_pool ) omp_next ; }; Element Description omp_databuf_len The length, in bytes, of the \"data buffer\" of the mbuf. The data buffer of the mbuf is everything except the os_mbuf structure (which is present in all types of mbufs) omp_mbuf_count Total number of mbufs in the pool when allocated. This is NOT the number of free mbufs in the pool! omp_pool The memory pool from which the mbufs are allocated omp_next This is a linked list pointer which chains memory pools. It is used by the system memory pool library struct os_mbuf_pkthdr { uint16_t omp_len ; uint16_t omp_flags ; STAILQ_ENTRY ( os_mbuf_pkthdr ) omp_next ; }; Element Description omp_len Length, in bytes, of the \"packet\". This is the sum of the user data in all the mbufs chained to the packet header mbuf (including the packet header mbuf) omp_flags Packet header flags. omp_next Linked list pointer to chain \"packets\". This can be used to add mbuf chains to a queue or linked list and is there for convenience. struct os_mbuf { uint8_t *om_data ; uint8_t om_flags ; uint8_t om_pkthdr_len ; uint16_t om_len ; struct os_mbuf_pool *om_omp ; SLIST_ENTRY ( os_mbuf ) om_next ; uint8_t om_databuf [ 0 ]; }; Element Description om_data Pointer to start of user data in mbuf data buffer om_flags mbuf flags field. Currently all flags unused. om_pkthdr_len The total length of all packet headers in the mbuf (mbuf packet header plus user packet header), in bytes om_len The length of the user data contained in this mbuf, in bytes om_omp Memory pool pointer. This is the mbuf pool from which this mbuf was allocated. om_next Pointer to next mbuf in packet chain om_databuf mbuf data buffer (accessor to start of mbuf data buffer). Note that the mbuf data buffer refers to the start of either the user data in normal mbufs or the start of the os mbuf packet header for packet header mbufs","title":"Data Structures"},{"location":"os/core_os/mbuf/mbuf/#list-of-functionsmacros","text":"The functions/macros available in mbuf are: Function/Macro Description OS_MBUF_PKTHDR Get a pointer to the os mbuf packet header of an mbuf. OS_MBUF_PKTHDR_TO_MBUF Get a pointer to the mbuf given a pointer to the os mbuf packet header. OS_MBUF_PKTLEN Get the length of an entire mbuf chain. OS_MBUF_DATA Cast the data pointer of an mbuf to a given type. OS_MBUF_USRHDR Get a pointer to the user packet header of an mbuf. OS_MBUF_USRHDR_LEN Retrieve the length of the user packet header in an mbuf. OS_MBUF_LEADINGSPACE Get the amount of leading space in an mbuf (in bytes). OS_MBUF_TRAILINGSPACE Get the amount of trailing space in an mbuf (in bytes). os_mbuf_adj Trims the given number of bytes from either the head (if positive) or tail (if negative) of an mbuf chain. os_mbuf_append Appends a data buffer of the given length to the end of an mbuf chain. os_mbuf_concat Attaches a second mbuf chain onto the end of the first. os_mbuf_copydata Copy data from an mbuf chain. os_mbuf_copyinto Copies the contents of a flat buffer into an mbuf chain. os_mbuf_dup Duplicate a chain of mbufs. os_mbuf_extend Increases the length of an mbuf chain by the specified amount. os_mbuf_free_chain Frees a chain of mbufs. os_mbuf_get Get an mbuf from the mbuf pool. os_mbuf_get_pkthdr Allocates a packet header mbuf from the given mbuf pool. Adds a user header to the packet header mbuf. os_mbuf_memcmp Performs a memory compare of the specified region of an mbuf chain against a flat buffer. os_mbuf_off Given an offset in the packet, return the mbuf and the offset in that mbuf where byte 'off' is located. os_mbuf_pool_init nitialize an mbuf pool. os_mbuf_prepend Increases the length of an mbuf chain by adding data to the front. os_mbuf_pullup Rearrange an mbuf chain so that the given length of bytes are contiguous and in the data area of an mbuf.","title":"List of Functions/Macros"},{"location":"os/core_os/mbuf/os_mbuf_adj/","text":"os_mbuf_adj void os_mbuf_adj ( struct os_mbuf *mp , int req_len ); Trims req_len bytes from either the head (if positive) or tail (if negative) of an mbuf chain. Adjusts the packet length of the mbuf chain if mp points to a packet header mbuf. When trimming from the head, no mbufs are freed. When trimming from the tail, any mbufs of zero length left at the end of the chain are freed. Arguments Arguments Description mp Pointer to mbuf. Can be head of a chain of mbufs, a single mbuf or a packet header mbuf req_len Number of bytes to trim from head or tail of mbuf Returned values None Notes Example uint16_t pktlen ; struct os_mbuf *om ; struct my_pkt_header hdr ; /* Get mbuf chain length */ pktlen = OS_MBUF_PKTLEN ( om ); /* Strip header from mbuf chain */ os_mbuf_adj ( om , sizeof ( struct my_pkt_header )); pktlen -= sizeof ( struct my_pkt_header ); /* New packet length should be old packet length minus stripped header */ assert ( pktlen == OS_MBUF_PKTLEN ( om ));","title":"os_mbuf_adj"},{"location":"os/core_os/mbuf/os_mbuf_adj/#os_mbuf_adj","text":"void os_mbuf_adj ( struct os_mbuf *mp , int req_len ); Trims req_len bytes from either the head (if positive) or tail (if negative) of an mbuf chain. Adjusts the packet length of the mbuf chain if mp points to a packet header mbuf. When trimming from the head, no mbufs are freed. When trimming from the tail, any mbufs of zero length left at the end of the chain are freed.","title":" os_mbuf_adj"},{"location":"os/core_os/mbuf/os_mbuf_adj/#arguments","text":"Arguments Description mp Pointer to mbuf. Can be head of a chain of mbufs, a single mbuf or a packet header mbuf req_len Number of bytes to trim from head or tail of mbuf","title":"Arguments"},{"location":"os/core_os/mbuf/os_mbuf_adj/#returned-values","text":"None","title":"Returned values"},{"location":"os/core_os/mbuf/os_mbuf_adj/#notes","text":"","title":"Notes"},{"location":"os/core_os/mbuf/os_mbuf_adj/#example","text":"uint16_t pktlen ; struct os_mbuf *om ; struct my_pkt_header hdr ; /* Get mbuf chain length */ pktlen = OS_MBUF_PKTLEN ( om ); /* Strip header from mbuf chain */ os_mbuf_adj ( om , sizeof ( struct my_pkt_header )); pktlen -= sizeof ( struct my_pkt_header ); /* New packet length should be old packet length minus stripped header */ assert ( pktlen == OS_MBUF_PKTLEN ( om ));","title":"Example"},{"location":"os/core_os/mbuf/os_mbuf_append/","text":"os_mbuf_append int os_mbuf_append ( struct os_mbuf *om , const void *data , uint16_t len ) Appends a data buffer of length len to the end of an mbuf chain, adjusting packet length if om is a packet header mbuf. If not enough trailing space exists at the end of the mbuf chain, mbufs are allocated to hold the data. Arguments Arguments Description om Pointer to mbuf. Can be head of a chain of mbufs, a single mbuf or a packet header mbuf data Pointer to data buffer to copy from len Number of bytes to copy from data buffer to the end of the mbuf Returned values 0: success OS_ENOMEM : Could not allocate enough mbufs to hold data. OS_EINVAL : om was NULL on entry. Notes If not enough mbufs were available the packet header length of the mbuf may get adjusted even though the entire data buffer was not appended to the end of the mbuf. If any mbufs are allocated, they are allocated from the same pool as om Example int rc ; uint16_t pktlen ; struct os_mbuf *om ; struct my_data_struct my_data ; /* Get initial packet length */ pktlen = OS_MBUF_PKTLEN ( om ); /* Append \"my_data\" to end of mbuf, freeing mbuf if unable to append all the data */ rc = os_mbuf_append ( om , &my_data , sizeof ( struct my_pkt_header )); if ( rc ) { os_mbuf_free_chain ( om ); } pktlen += sizeof ( struct my_pkt_header ); /* New packet length should be initial packet length plus length of \"my_data\" */ assert ( pktlen == OS_MBUF_PKTLEN ( om ));","title":"os_mbuf_append"},{"location":"os/core_os/mbuf/os_mbuf_append/#os_mbuf_append","text":"int os_mbuf_append ( struct os_mbuf *om , const void *data , uint16_t len ) Appends a data buffer of length len to the end of an mbuf chain, adjusting packet length if om is a packet header mbuf. If not enough trailing space exists at the end of the mbuf chain, mbufs are allocated to hold the data.","title":" os_mbuf_append"},{"location":"os/core_os/mbuf/os_mbuf_append/#arguments","text":"Arguments Description om Pointer to mbuf. Can be head of a chain of mbufs, a single mbuf or a packet header mbuf data Pointer to data buffer to copy from len Number of bytes to copy from data buffer to the end of the mbuf","title":"Arguments"},{"location":"os/core_os/mbuf/os_mbuf_append/#returned-values","text":"0: success OS_ENOMEM : Could not allocate enough mbufs to hold data. OS_EINVAL : om was NULL on entry.","title":"Returned values"},{"location":"os/core_os/mbuf/os_mbuf_append/#notes","text":"If not enough mbufs were available the packet header length of the mbuf may get adjusted even though the entire data buffer was not appended to the end of the mbuf. If any mbufs are allocated, they are allocated from the same pool as om","title":"Notes"},{"location":"os/core_os/mbuf/os_mbuf_append/#example","text":"int rc ; uint16_t pktlen ; struct os_mbuf *om ; struct my_data_struct my_data ; /* Get initial packet length */ pktlen = OS_MBUF_PKTLEN ( om ); /* Append \"my_data\" to end of mbuf, freeing mbuf if unable to append all the data */ rc = os_mbuf_append ( om , &my_data , sizeof ( struct my_pkt_header )); if ( rc ) { os_mbuf_free_chain ( om ); } pktlen += sizeof ( struct my_pkt_header ); /* New packet length should be initial packet length plus length of \"my_data\" */ assert ( pktlen == OS_MBUF_PKTLEN ( om ));","title":"Example"},{"location":"os/core_os/mbuf/os_mbuf_concat/","text":"os_mbuf_concat void os_mbuf_concat ( struct os_mbuf *first , struct os_mbuf *second ) Attaches a second mbuf chain onto the end of the first. If the first chain contains a packet header, the header's length is updated. If the second chain has a packet header, its header is cleared. Arguments Arguments Description first Pointer to first mbuf chain second Pointer to second mbuf chain Returned values None Notes No data is copied or moved nor are any mbufs freed. Example uint16_t pktlen1 ; uint16_t pktlen2 ; struct os_mbuf *pkt1 ; struct os_mbuf *pkt2 ; /* Get initial packet lengths */ pktlen1 = OS_MBUF_PKTLEN ( pkt1 ); pktlen2 = OS_MBUF_PKTLEN ( pkt2 ); /* Add pkt2 to end of pkt1 */ os_mbuf_concat ( pkt1 , pkt2 ); /* New packet length should be sum of pkt1 and pkt2 */ assert (( pktlen1 + pktlen2 ) == OS_MBUF_PKTLEN ( pkt1 ));","title":"os_mbuf_concat"},{"location":"os/core_os/mbuf/os_mbuf_concat/#os_mbuf_concat","text":"void os_mbuf_concat ( struct os_mbuf *first , struct os_mbuf *second ) Attaches a second mbuf chain onto the end of the first. If the first chain contains a packet header, the header's length is updated. If the second chain has a packet header, its header is cleared.","title":" os_mbuf_concat"},{"location":"os/core_os/mbuf/os_mbuf_concat/#arguments","text":"Arguments Description first Pointer to first mbuf chain second Pointer to second mbuf chain","title":"Arguments"},{"location":"os/core_os/mbuf/os_mbuf_concat/#returned-values","text":"None","title":"Returned values"},{"location":"os/core_os/mbuf/os_mbuf_concat/#notes","text":"No data is copied or moved nor are any mbufs freed.","title":"Notes"},{"location":"os/core_os/mbuf/os_mbuf_concat/#example","text":"uint16_t pktlen1 ; uint16_t pktlen2 ; struct os_mbuf *pkt1 ; struct os_mbuf *pkt2 ; /* Get initial packet lengths */ pktlen1 = OS_MBUF_PKTLEN ( pkt1 ); pktlen2 = OS_MBUF_PKTLEN ( pkt2 ); /* Add pkt2 to end of pkt1 */ os_mbuf_concat ( pkt1 , pkt2 ); /* New packet length should be sum of pkt1 and pkt2 */ assert (( pktlen1 + pktlen2 ) == OS_MBUF_PKTLEN ( pkt1 ));","title":"Example"},{"location":"os/core_os/mbuf/os_mbuf_copydata/","text":"os_mbuf_copydata int os_mbuf_copydata ( const struct os_mbuf *m , int off , int len , void *dst ) Copy data from an mbuf chain starting off bytes from the beginning, continuing for len bytes, into the indicated buffer. Arguments Arguments Description m Pointer to mbuf chain off Start copy offset, in bytes, from beginning of mbuf chain len Number of bytes to copy dst Data buffer to copy into Returned values 0: success. -1: The mbuf does not contain enough data Example int rc ; struct os_mbuf *om ; struct my_hdr_1 my_hdr1 ; struct my_hdr_2 my_hdr2 ; /* Header 1 and Header 2 are contiguous in packet at start. Retrieve them from the mbuf chain */ rc = os_mbuf_copydata ( om , 0 , sizeof ( struct my_hdr_1 ), &my_hdr1 ); if ( rc ) { /* error! */ return -1 ; } rc = os_mbuf_copydata ( om , sizeof ( struct my_hdr_1 ), sizeof ( struct my_hdr_2 ), &my_hdr2 ); if ( rc ) { /* error! */ return -1 ; }","title":"os_mbuf_copydata"},{"location":"os/core_os/mbuf/os_mbuf_copydata/#os_mbuf_copydata","text":"int os_mbuf_copydata ( const struct os_mbuf *m , int off , int len , void *dst ) Copy data from an mbuf chain starting off bytes from the beginning, continuing for len bytes, into the indicated buffer.","title":" os_mbuf_copydata"},{"location":"os/core_os/mbuf/os_mbuf_copydata/#arguments","text":"Arguments Description m Pointer to mbuf chain off Start copy offset, in bytes, from beginning of mbuf chain len Number of bytes to copy dst Data buffer to copy into","title":"Arguments"},{"location":"os/core_os/mbuf/os_mbuf_copydata/#returned-values","text":"0: success. -1: The mbuf does not contain enough data","title":"Returned values"},{"location":"os/core_os/mbuf/os_mbuf_copydata/#example","text":"int rc ; struct os_mbuf *om ; struct my_hdr_1 my_hdr1 ; struct my_hdr_2 my_hdr2 ; /* Header 1 and Header 2 are contiguous in packet at start. Retrieve them from the mbuf chain */ rc = os_mbuf_copydata ( om , 0 , sizeof ( struct my_hdr_1 ), &my_hdr1 ); if ( rc ) { /* error! */ return -1 ; } rc = os_mbuf_copydata ( om , sizeof ( struct my_hdr_1 ), sizeof ( struct my_hdr_2 ), &my_hdr2 ); if ( rc ) { /* error! */ return -1 ; }","title":"Example"},{"location":"os/core_os/mbuf/os_mbuf_copyinto/","text":"os_mbuf_copyinto int os_mbuf_copyinto ( struct os_mbuf *om , int off , const void *src , int len ); Copies the contents of a flat buffer into an mbuf chain, starting at the specified destination offset. If the mbuf is too small for the source data, it is extended as necessary. If the destination mbuf contains a packet header, the header length is updated. Arguments Arguments Description om Pointer to mbuf chain off Start copy offset, in bytes, from beginning of mbuf chain src Address from which bytes are copied len Number of bytes to copy from src Returned values 0: success. All other values indicate an error. Example int rc ; uint16_t pktlen ; struct os_mbuf *om ; struct my_data_struct my_data ; /* Get initial packet length */ pktlen = OS_MBUF_PKTLEN ( om ); /* Copy \"my_data\" into mbuf */ rc = os_mbuf_copyinto ( om , 0 , &my_data , sizeof ( struct my_data_struct )); if ( rc ) { os_mbuf_free_chain ( om ); return ; } /* Packet length should have increased by size of \"my_data\" */ pktlen += sizeof ( struct my_data_struct ); assert ( pktlen == OS_MBUF_PKTLEN ( om ));","title":"os_mbuf_copyinto"},{"location":"os/core_os/mbuf/os_mbuf_copyinto/#os_mbuf_copyinto","text":"int os_mbuf_copyinto ( struct os_mbuf *om , int off , const void *src , int len ); Copies the contents of a flat buffer into an mbuf chain, starting at the specified destination offset. If the mbuf is too small for the source data, it is extended as necessary. If the destination mbuf contains a packet header, the header length is updated.","title":" os_mbuf_copyinto"},{"location":"os/core_os/mbuf/os_mbuf_copyinto/#arguments","text":"Arguments Description om Pointer to mbuf chain off Start copy offset, in bytes, from beginning of mbuf chain src Address from which bytes are copied len Number of bytes to copy from src","title":"Arguments"},{"location":"os/core_os/mbuf/os_mbuf_copyinto/#returned-values","text":"0: success. All other values indicate an error.","title":"Returned values"},{"location":"os/core_os/mbuf/os_mbuf_copyinto/#example","text":"int rc ; uint16_t pktlen ; struct os_mbuf *om ; struct my_data_struct my_data ; /* Get initial packet length */ pktlen = OS_MBUF_PKTLEN ( om ); /* Copy \"my_data\" into mbuf */ rc = os_mbuf_copyinto ( om , 0 , &my_data , sizeof ( struct my_data_struct )); if ( rc ) { os_mbuf_free_chain ( om ); return ; } /* Packet length should have increased by size of \"my_data\" */ pktlen += sizeof ( struct my_data_struct ); assert ( pktlen == OS_MBUF_PKTLEN ( om ));","title":"Example"},{"location":"os/core_os/mbuf/os_mbuf_dup/","text":"os_mbuf_dup struct os_mbuf *os_mbuf_dup ( struct os_mbuf *om ) Duplicate a chain of mbufs. Return the start of the duplicated chain. Arguments Arguments Description om Pointer to mbuf chain to duplicate Returned values Pointer to the duplicated chain or NULL if not enough mbufs were available to duplicate the chain. Example struct os_mbuf *om ; struct os_mbuf *new_om ; /* Make a copy of om, returning -1 if not able to duplicate om */ new_om = os_mbuf_dup ( om ); if ( !new_om ) { return -1 ; }","title":"os_mbuf_dup"},{"location":"os/core_os/mbuf/os_mbuf_dup/#os_mbuf_dup","text":"struct os_mbuf *os_mbuf_dup ( struct os_mbuf *om ) Duplicate a chain of mbufs. Return the start of the duplicated chain.","title":" os_mbuf_dup"},{"location":"os/core_os/mbuf/os_mbuf_dup/#arguments","text":"Arguments Description om Pointer to mbuf chain to duplicate","title":"Arguments"},{"location":"os/core_os/mbuf/os_mbuf_dup/#returned-values","text":"Pointer to the duplicated chain or NULL if not enough mbufs were available to duplicate the chain.","title":"Returned values"},{"location":"os/core_os/mbuf/os_mbuf_dup/#example","text":"struct os_mbuf *om ; struct os_mbuf *new_om ; /* Make a copy of om, returning -1 if not able to duplicate om */ new_om = os_mbuf_dup ( om ); if ( !new_om ) { return -1 ; }","title":"Example"},{"location":"os/core_os/mbuf/os_mbuf_extend/","text":"os_mbuf_extend void *os_mbuf_extend ( struct os_mbuf *om , uint16_t len ); Increases the length of an mbuf chain by the specified amount. If there is not sufficient room in the last buffer, a new buffer is allocated and appended to the chain. It is an error to request more data than can fit in a single buffer. Arguments Arguments Description om Pointer to mbuf chain len Number of bytes to increase packet header Returned values Pointer to start of extended data. Caller is guaranteed that there are at least len bytes from this pointer to the end of the mbuf. Returns NULL if extension fails due to insufficient mbufs or len too large. Example uint8_t *dptr ; struct os_mbuf *om ; struct my_data_struct my_data ; /* Obtain enough room to add \"my_data\" to an mbuf chain */ dptr = os_mbuf_extend ( om , sizeof ( struct my_data_struct )); if ( dptr ) { memcpy ( dptr , &my_data , sizeof ( struct my_data_struct )); }","title":"os_mbuf_extend"},{"location":"os/core_os/mbuf/os_mbuf_extend/#os_mbuf_extend","text":"void *os_mbuf_extend ( struct os_mbuf *om , uint16_t len ); Increases the length of an mbuf chain by the specified amount. If there is not sufficient room in the last buffer, a new buffer is allocated and appended to the chain. It is an error to request more data than can fit in a single buffer.","title":" os_mbuf_extend"},{"location":"os/core_os/mbuf/os_mbuf_extend/#arguments","text":"Arguments Description om Pointer to mbuf chain len Number of bytes to increase packet header","title":"Arguments"},{"location":"os/core_os/mbuf/os_mbuf_extend/#returned-values","text":"Pointer to start of extended data. Caller is guaranteed that there are at least len bytes from this pointer to the end of the mbuf. Returns NULL if extension fails due to insufficient mbufs or len too large.","title":"Returned values"},{"location":"os/core_os/mbuf/os_mbuf_extend/#example","text":"uint8_t *dptr ; struct os_mbuf *om ; struct my_data_struct my_data ; /* Obtain enough room to add \"my_data\" to an mbuf chain */ dptr = os_mbuf_extend ( om , sizeof ( struct my_data_struct )); if ( dptr ) { memcpy ( dptr , &my_data , sizeof ( struct my_data_struct )); }","title":"Example"},{"location":"os/core_os/mbuf/os_mbuf_free_chain/","text":"os_mbuf_free_chain int os_mbuf_free_chain ( struct os_mbuf *om ); Frees a chain of mbufs Arguments Arguments Description om Pointer to mbuf chain Returned values 0: success Any other value indicates error Notes Note that for each mbuf in the chain, os_mbuf_free() is called. Example int rc ; struct os_mbuf *om ; /* Free mbuf chain */ rc = os_mbuf_free_chain ( om ); assert ( rc == 0 );","title":"os_mbuf_free_chain"},{"location":"os/core_os/mbuf/os_mbuf_free_chain/#os_mbuf_free_chain","text":"int os_mbuf_free_chain ( struct os_mbuf *om ); Frees a chain of mbufs","title":" os_mbuf_free_chain"},{"location":"os/core_os/mbuf/os_mbuf_free_chain/#arguments","text":"Arguments Description om Pointer to mbuf chain","title":"Arguments"},{"location":"os/core_os/mbuf/os_mbuf_free_chain/#returned-values","text":"0: success Any other value indicates error","title":"Returned values"},{"location":"os/core_os/mbuf/os_mbuf_free_chain/#notes","text":"Note that for each mbuf in the chain, os_mbuf_free() is called.","title":"Notes"},{"location":"os/core_os/mbuf/os_mbuf_free_chain/#example","text":"int rc ; struct os_mbuf *om ; /* Free mbuf chain */ rc = os_mbuf_free_chain ( om ); assert ( rc == 0 );","title":"Example"},{"location":"os/core_os/mbuf/os_mbuf_get/","text":"os_mbuf_get struct os_mbuf *os_mbuf_get ( struct os_mbuf_pool *omp , uint16_t leadingspace ) Get an mbuf from the mbuf pool. The mbuf is allocated, and initialized prior to being returned. The eadingspace parameter allows the user to specify the amount of leading space in the allocated mbuf. Arguments Arguments Description om Pointer to mbuf pool from which to allocate mbuf leadingspace Amount of leading space in allocated mbuf. Request cannot exceed the mbuf data buffer size. Returned values Returns a pointer to the allocated mbuf or NULL if there are no mbufs available or leadingspace was too large. Notes In most typical applications, the application developer does not need to call os_mbuf_get() ; the other API will do this automatically. However, this API is provided for convenience as mbufs can also be a simple way to allocate temporary chunks of memory. Example struct os_mbuf *om ; /* Get an mbuf */ om = os_mbuf_get ( &g_mbuf_pool , 0 ); if ( om ) { /* we have allocated an mbuf from the pool */ }","title":"os_mbuf_get"},{"location":"os/core_os/mbuf/os_mbuf_get/#os_mbuf_get","text":"struct os_mbuf *os_mbuf_get ( struct os_mbuf_pool *omp , uint16_t leadingspace ) Get an mbuf from the mbuf pool. The mbuf is allocated, and initialized prior to being returned. The eadingspace parameter allows the user to specify the amount of leading space in the allocated mbuf.","title":"os_mbuf_get"},{"location":"os/core_os/mbuf/os_mbuf_get/#arguments","text":"Arguments Description om Pointer to mbuf pool from which to allocate mbuf leadingspace Amount of leading space in allocated mbuf. Request cannot exceed the mbuf data buffer size.","title":"Arguments"},{"location":"os/core_os/mbuf/os_mbuf_get/#returned-values","text":"Returns a pointer to the allocated mbuf or NULL if there are no mbufs available or leadingspace was too large.","title":"Returned values"},{"location":"os/core_os/mbuf/os_mbuf_get/#notes","text":"In most typical applications, the application developer does not need to call os_mbuf_get() ; the other API will do this automatically. However, this API is provided for convenience as mbufs can also be a simple way to allocate temporary chunks of memory.","title":"Notes"},{"location":"os/core_os/mbuf/os_mbuf_get/#example","text":"struct os_mbuf *om ; /* Get an mbuf */ om = os_mbuf_get ( &g_mbuf_pool , 0 ); if ( om ) { /* we have allocated an mbuf from the pool */ }","title":"Example"},{"location":"os/core_os/mbuf/os_mbuf_get_pkthdr/","text":"os_mbuf_get_pkthdr struct os_mbuf *os_mbuf_get_pkthdr ( struct os_mbuf_pool *omp , uint8_t pkthdr_len ); Allocates a packet header mbuf from the mbuf pool pointed to by omp . Adds a user header of length pkthdr_len to packet header mbuf. Arguments Arguments Description om Pointer to mbuf pool from which to allocate mbuf pkthdr_len The user header packet length to allocate for the packet header mbuf Returned values Returns a pointer to the allocated mbuf or NULL if there are no mbufs available or the user packet header was too large. Notes The packet header mbuf returned will have its data pointer incremented by the sizeof(struct os_mbuf_pkthdr) as well as the amount of user header data (i.e. pkthdr_len ). In other words, the data pointer is offset from the start of the mbuf by: sizeof(struct os_mbuf) + sizeof(struct os_mbuf_pkthdr) + pkthdr_len . The om_pkthdr_len element in the allocated mbuf is set to: sizeof(struct os_mbuf_pkthdr) + pkthdr_len . Example struct os_mbuf *om ; struct my_user_header my_hdr ; /* Get a packet header mbuf with a user header in it */ om = os_mbuf_get_pkthdr ( &g_mbuf_pool , sizeof ( struct my_user_header )); if ( om ) { /* Packet header mbuf was allocated */ }","title":"os_mbuf_get_pkthdr"},{"location":"os/core_os/mbuf/os_mbuf_get_pkthdr/#os_mbuf_get_pkthdr","text":"struct os_mbuf *os_mbuf_get_pkthdr ( struct os_mbuf_pool *omp , uint8_t pkthdr_len ); Allocates a packet header mbuf from the mbuf pool pointed to by omp . Adds a user header of length pkthdr_len to packet header mbuf.","title":"os_mbuf_get_pkthdr"},{"location":"os/core_os/mbuf/os_mbuf_get_pkthdr/#arguments","text":"Arguments Description om Pointer to mbuf pool from which to allocate mbuf pkthdr_len The user header packet length to allocate for the packet header mbuf","title":"Arguments"},{"location":"os/core_os/mbuf/os_mbuf_get_pkthdr/#returned-values","text":"Returns a pointer to the allocated mbuf or NULL if there are no mbufs available or the user packet header was too large.","title":"Returned values"},{"location":"os/core_os/mbuf/os_mbuf_get_pkthdr/#notes","text":"The packet header mbuf returned will have its data pointer incremented by the sizeof(struct os_mbuf_pkthdr) as well as the amount of user header data (i.e. pkthdr_len ). In other words, the data pointer is offset from the start of the mbuf by: sizeof(struct os_mbuf) + sizeof(struct os_mbuf_pkthdr) + pkthdr_len . The om_pkthdr_len element in the allocated mbuf is set to: sizeof(struct os_mbuf_pkthdr) + pkthdr_len .","title":"Notes"},{"location":"os/core_os/mbuf/os_mbuf_get_pkthdr/#example","text":"struct os_mbuf *om ; struct my_user_header my_hdr ; /* Get a packet header mbuf with a user header in it */ om = os_mbuf_get_pkthdr ( &g_mbuf_pool , sizeof ( struct my_user_header )); if ( om ) { /* Packet header mbuf was allocated */ }","title":"Example"},{"location":"os/core_os/mbuf/os_mbuf_memcmp/","text":"os_mbuf_memcmp int os_mbuf_memcmp ( const struct os_mbuf *om , int off , const void *data , int len ) Performs a memory compare of the specified region of an mbuf chain against a flat buffer. Arguments Arguments Description om Pointer to mbuf off Offset, in bytes, from start of mbuf to start of comparison data Pointer to flat data buffer to compare len Number of bytes to compare Returned values A value of zero means the memory regions are identical; all other values represent either an error or a value returned from memcmp. Notes This function will compare bytes starting from off bytes from the start of the mbuf chain with a data buffer. Example int rc ; struct os_mbuf *om ; uint8_t my_data_buffer [ 32 ]; /* Get a packet header mbuf with a user header in it */ rc = os_mbuf_memcmp ( om , 0 , my_data_buffer , 32 ); if ( !rc ) { /* \"my_data_buffer\" and the data from offset 0 in the mbuf chain are identical! */ }","title":"os_mbuf_memcmp"},{"location":"os/core_os/mbuf/os_mbuf_memcmp/#os_mbuf_memcmp","text":"int os_mbuf_memcmp ( const struct os_mbuf *om , int off , const void *data , int len ) Performs a memory compare of the specified region of an mbuf chain against a flat buffer.","title":"os_mbuf_memcmp"},{"location":"os/core_os/mbuf/os_mbuf_memcmp/#arguments","text":"Arguments Description om Pointer to mbuf off Offset, in bytes, from start of mbuf to start of comparison data Pointer to flat data buffer to compare len Number of bytes to compare","title":"Arguments"},{"location":"os/core_os/mbuf/os_mbuf_memcmp/#returned-values","text":"A value of zero means the memory regions are identical; all other values represent either an error or a value returned from memcmp.","title":"Returned values"},{"location":"os/core_os/mbuf/os_mbuf_memcmp/#notes","text":"This function will compare bytes starting from off bytes from the start of the mbuf chain with a data buffer.","title":"Notes"},{"location":"os/core_os/mbuf/os_mbuf_memcmp/#example","text":"int rc ; struct os_mbuf *om ; uint8_t my_data_buffer [ 32 ]; /* Get a packet header mbuf with a user header in it */ rc = os_mbuf_memcmp ( om , 0 , my_data_buffer , 32 ); if ( !rc ) { /* \"my_data_buffer\" and the data from offset 0 in the mbuf chain are identical! */ }","title":"Example"},{"location":"os/core_os/mbuf/os_mbuf_off/","text":"os_mbuf_off struct os_mbuf *os_mbuf_off ( struct os_mbuf *om , int off , int *out_off ) Given an offset in the packet (i.e. user data byte offset in the mbuf chain), return the mbuf and the offset in that mbuf where byte 'off' is located. Note that the offset is returned in out_off . Arguments Arguments Description om Pointer to mbuf off Location in mbuf chain of desired byte offset out_off Pointer to storage for the relative offset of the absolute location in the returned mbuf Returned values NULL if the offset is not within the mbuf chain or om points to NULL . Notes The user is allowed to call this function with the length of the mbuf chain but no greater. This allows the user to get the mbuf and offset (in that mbuf) where the next user data byte should be written. While this api is provided to the user, other APIs are expected to be used by the applciation developer (i.e. os_mbuf_append() or os_mbuf_copyinto() ). Example int relative_offset ; uint16_t pktlen ; struct os_mbuf *om ; struct os_mbuf *tmp ; /* Append a new line character to end of mbuf data */ pktlen = OS_MBUF_PKTLEN ( om ); relative_offset = 0 ; tmp = os_mbuf_off ( om , pktlen , &relative_offset ); if ( tmp ) { /* Offset found. */ tmp->om_data [ relative_offset ] = '\\n' ; } else { /* * This mbuf does not contain enough bytes so this is an invalid offset. * In other words, the mbuf is less than 62 bytes in length. */ }","title":"os_mbuf_off"},{"location":"os/core_os/mbuf/os_mbuf_off/#os_mbuf_off","text":"struct os_mbuf *os_mbuf_off ( struct os_mbuf *om , int off , int *out_off ) Given an offset in the packet (i.e. user data byte offset in the mbuf chain), return the mbuf and the offset in that mbuf where byte 'off' is located. Note that the offset is returned in out_off .","title":"os_mbuf_off"},{"location":"os/core_os/mbuf/os_mbuf_off/#arguments","text":"Arguments Description om Pointer to mbuf off Location in mbuf chain of desired byte offset out_off Pointer to storage for the relative offset of the absolute location in the returned mbuf","title":"Arguments"},{"location":"os/core_os/mbuf/os_mbuf_off/#returned-values","text":"NULL if the offset is not within the mbuf chain or om points to NULL .","title":"Returned values"},{"location":"os/core_os/mbuf/os_mbuf_off/#notes","text":"The user is allowed to call this function with the length of the mbuf chain but no greater. This allows the user to get the mbuf and offset (in that mbuf) where the next user data byte should be written. While this api is provided to the user, other APIs are expected to be used by the applciation developer (i.e. os_mbuf_append() or os_mbuf_copyinto() ).","title":"Notes"},{"location":"os/core_os/mbuf/os_mbuf_off/#example","text":"int relative_offset ; uint16_t pktlen ; struct os_mbuf *om ; struct os_mbuf *tmp ; /* Append a new line character to end of mbuf data */ pktlen = OS_MBUF_PKTLEN ( om ); relative_offset = 0 ; tmp = os_mbuf_off ( om , pktlen , &relative_offset ); if ( tmp ) { /* Offset found. */ tmp->om_data [ relative_offset ] = '\\n' ; } else { /* * This mbuf does not contain enough bytes so this is an invalid offset. * In other words, the mbuf is less than 62 bytes in length. */ }","title":"Example"},{"location":"os/core_os/mbuf/os_mbuf_pool_init/","text":"os_mbuf_pool_init int os_mbuf_pool_init ( struct os_mbuf_pool *omp , struct os_mempool *mp , uint16_t buf_len , uint16_t nbufs ) Initialize an mbuf pool Arguments Arguments Description omp Pointer to mbuf pool to initialize mp Pointer to memory pool used by mbuf pool buf_len The size of the memory blocks in the memory pool used by the mbuf pool nbufs The number of mbufs in the pool Returned values 0 on success; all other values indicate an error. Notes The parameter buf_len is the total size of the memory block. This must accommodate the os_mbuf structure, the os_mbuf_pkthdr structure, any user headers plus the desired amount of user data. Example #define MBUF_PKTHDR_OVERHEAD sizeof(struct os_mbuf_pkthdr) + sizeof(struct user_hdr) #define MBUF_MEMBLOCK_OVERHEAD sizeof(struct os_mbuf) + MBUF_PKTHDR_OVERHEAD #define MBUF_NUM_MBUFS (32) #define MBUF_PAYLOAD_SIZE (64) #define MBUF_BUF_SIZE OS_ALIGN(MBUF_PAYLOAD_SIZE, 4) #define MBUF_MEMBLOCK_SIZE (MBUF_BUF_SIZE + MBUF_MEMBLOCK_OVERHEAD) #define MBUF_MEMPOOL_SIZE OS_MEMPOOL_SIZE(MBUF_NUM_MBUFS, MBUF_MEMBLOCK_SIZE) struct os_mbuf_pool g_mbuf_pool ; struct os_mempool g_mbuf_mempool ; os_membuf_t g_mbuf_buffer [ MBUF_MEMPOOL_SIZE ]; void create_mbuf_pool ( void ) { int rc ; rc = os_mempool_init ( &g_mbuf_mempool , MBUF_NUM_MBUFS , MBUF_MEMBLOCK_SIZE , &g_mbuf_buffer [ 0 ], \"mbuf_pool\" ); assert ( rc == 0 ); rc = os_mbuf_pool_init ( &g_mbuf_pool , &g_mbuf_mempool , MBUF_MEMBLOCK_SIZE , MBUF_NUM_MBUFS ); assert ( rc == 0 ); }","title":"os_mbuf_pool_init"},{"location":"os/core_os/mbuf/os_mbuf_pool_init/#os_mbuf_pool_init","text":"int os_mbuf_pool_init ( struct os_mbuf_pool *omp , struct os_mempool *mp , uint16_t buf_len , uint16_t nbufs ) Initialize an mbuf pool","title":"os_mbuf_pool_init"},{"location":"os/core_os/mbuf/os_mbuf_pool_init/#arguments","text":"Arguments Description omp Pointer to mbuf pool to initialize mp Pointer to memory pool used by mbuf pool buf_len The size of the memory blocks in the memory pool used by the mbuf pool nbufs The number of mbufs in the pool","title":"Arguments"},{"location":"os/core_os/mbuf/os_mbuf_pool_init/#returned-values","text":"0 on success; all other values indicate an error.","title":"Returned values"},{"location":"os/core_os/mbuf/os_mbuf_pool_init/#notes","text":"The parameter buf_len is the total size of the memory block. This must accommodate the os_mbuf structure, the os_mbuf_pkthdr structure, any user headers plus the desired amount of user data.","title":"Notes"},{"location":"os/core_os/mbuf/os_mbuf_pool_init/#example","text":"#define MBUF_PKTHDR_OVERHEAD sizeof(struct os_mbuf_pkthdr) + sizeof(struct user_hdr) #define MBUF_MEMBLOCK_OVERHEAD sizeof(struct os_mbuf) + MBUF_PKTHDR_OVERHEAD #define MBUF_NUM_MBUFS (32) #define MBUF_PAYLOAD_SIZE (64) #define MBUF_BUF_SIZE OS_ALIGN(MBUF_PAYLOAD_SIZE, 4) #define MBUF_MEMBLOCK_SIZE (MBUF_BUF_SIZE + MBUF_MEMBLOCK_OVERHEAD) #define MBUF_MEMPOOL_SIZE OS_MEMPOOL_SIZE(MBUF_NUM_MBUFS, MBUF_MEMBLOCK_SIZE) struct os_mbuf_pool g_mbuf_pool ; struct os_mempool g_mbuf_mempool ; os_membuf_t g_mbuf_buffer [ MBUF_MEMPOOL_SIZE ]; void create_mbuf_pool ( void ) { int rc ; rc = os_mempool_init ( &g_mbuf_mempool , MBUF_NUM_MBUFS , MBUF_MEMBLOCK_SIZE , &g_mbuf_buffer [ 0 ], \"mbuf_pool\" ); assert ( rc == 0 ); rc = os_mbuf_pool_init ( &g_mbuf_pool , &g_mbuf_mempool , MBUF_MEMBLOCK_SIZE , MBUF_NUM_MBUFS ); assert ( rc == 0 ); }","title":"Example"},{"location":"os/core_os/mbuf/os_mbuf_prepend/","text":"os_mbuf_prepend struct os_mbuf *os_mbuf_prepend ( struct os_mbuf *om , int len ) Increases the length of an mbuf chain by adding data to the front. If there is insufficient room in the leading mbuf, additional mbufs are allocated and prepended as necessary. If this function fails to allocate an mbuf, the entire chain is freed. Arguments Arguments Description om Pointer to mbuf len Length, in bytes, to prepend Returned values Pointer to mbuf at head of chain; NULL if not enough mbufs were available to accommodate len . Notes If om is a packet header mbuf, the total length of the packet is adjusted by len . Note that the returned mbuf may not point to om if insufficient leading space was available in om . Example uint16_t pktlen ; struct os_mbuf *om ; struct os_mbuf *tmp ; /* Get initial packet length before prepend */ pktlen = OS_MBUF_PKTLEN ( om ); tmp = os_mbuf_prepend ( om , 32 ); if ( !tmp ) { /* Not able to prepend. The chain pointed to by *om has been freed */ return -1 ; } /* The packet length should equal the original length plus what we prepended */ assert (( pktlen + 32 ) == OS_MBUF_PKTLEN ( tmp ));","title":"os_mbuf_prepend"},{"location":"os/core_os/mbuf/os_mbuf_prepend/#os_mbuf_prepend","text":"struct os_mbuf *os_mbuf_prepend ( struct os_mbuf *om , int len ) Increases the length of an mbuf chain by adding data to the front. If there is insufficient room in the leading mbuf, additional mbufs are allocated and prepended as necessary. If this function fails to allocate an mbuf, the entire chain is freed.","title":"os_mbuf_prepend"},{"location":"os/core_os/mbuf/os_mbuf_prepend/#arguments","text":"Arguments Description om Pointer to mbuf len Length, in bytes, to prepend","title":"Arguments"},{"location":"os/core_os/mbuf/os_mbuf_prepend/#returned-values","text":"Pointer to mbuf at head of chain; NULL if not enough mbufs were available to accommodate len .","title":"Returned values"},{"location":"os/core_os/mbuf/os_mbuf_prepend/#notes","text":"If om is a packet header mbuf, the total length of the packet is adjusted by len . Note that the returned mbuf may not point to om if insufficient leading space was available in om .","title":"Notes"},{"location":"os/core_os/mbuf/os_mbuf_prepend/#example","text":"uint16_t pktlen ; struct os_mbuf *om ; struct os_mbuf *tmp ; /* Get initial packet length before prepend */ pktlen = OS_MBUF_PKTLEN ( om ); tmp = os_mbuf_prepend ( om , 32 ); if ( !tmp ) { /* Not able to prepend. The chain pointed to by *om has been freed */ return -1 ; } /* The packet length should equal the original length plus what we prepended */ assert (( pktlen + 32 ) == OS_MBUF_PKTLEN ( tmp ));","title":"Example"},{"location":"os/core_os/mbuf/os_mbuf_pullup/","text":"os_mbuf_pullup struct os_mbuf *os_mbuf_pullup ( struct os_mbuf *om , uint16_t len ) Rearrange an mbuf chain so that len bytes are contiguous, and in the data area of an mbuf (so that OS_MBUF_DATA() will work on a structure of size len .) Returns the resulting mbuf chain on success, free's it and returns NULL on failure. Arguments Arguments Description om Pointer to mbuf len Length, in bytes, to pullup (make contiguous in mbuf) Returned values Pointer to mbuf at head of chain; NULL if not enough mbufs were available to accommodate len or if the requested pullup size was too large. Notes Hopefully it is apparent to the user that you cannot pullup more bytes than the mbuf can accommodate. Pullup does not allocate more than one mbuf; the entire pullup length must be contained within a single mbuf. The mbuf that is being pulled up into does not need to be a packet header mbuf; it can be a normal mbuf. The user should note that the maximum pullup length does depend on the type of mbuf being pulled up into (a packet header or normal mbuf). Example struct os_mbuf *om ; struct os_mbuf *tmp ; struct my_header_struct my_header ; /* Make sure \"my_header\" is contiguous in the mbuf */ tmp = os_mbuf_pullup ( om , sizeof ( my_header_struct )); if ( !tmp ) { /* Pullup failed. The chain pointed to by *om has been freed */ return -1 ; } /* copy data from mbuf into header structure */ memcpy ( &my_header , tmp->om_data , sizeof ( struct my_header_struct ));","title":"os_mbuf_pullup"},{"location":"os/core_os/mbuf/os_mbuf_pullup/#os_mbuf_pullup","text":"struct os_mbuf *os_mbuf_pullup ( struct os_mbuf *om , uint16_t len ) Rearrange an mbuf chain so that len bytes are contiguous, and in the data area of an mbuf (so that OS_MBUF_DATA() will work on a structure of size len .) Returns the resulting mbuf chain on success, free's it and returns NULL on failure.","title":"os_mbuf_pullup"},{"location":"os/core_os/mbuf/os_mbuf_pullup/#arguments","text":"Arguments Description om Pointer to mbuf len Length, in bytes, to pullup (make contiguous in mbuf)","title":"Arguments"},{"location":"os/core_os/mbuf/os_mbuf_pullup/#returned-values","text":"Pointer to mbuf at head of chain; NULL if not enough mbufs were available to accommodate len or if the requested pullup size was too large.","title":"Returned values"},{"location":"os/core_os/mbuf/os_mbuf_pullup/#notes","text":"Hopefully it is apparent to the user that you cannot pullup more bytes than the mbuf can accommodate. Pullup does not allocate more than one mbuf; the entire pullup length must be contained within a single mbuf. The mbuf that is being pulled up into does not need to be a packet header mbuf; it can be a normal mbuf. The user should note that the maximum pullup length does depend on the type of mbuf being pulled up into (a packet header or normal mbuf).","title":"Notes"},{"location":"os/core_os/mbuf/os_mbuf_pullup/#example","text":"struct os_mbuf *om ; struct os_mbuf *tmp ; struct my_header_struct my_header ; /* Make sure \"my_header\" is contiguous in the mbuf */ tmp = os_mbuf_pullup ( om , sizeof ( my_header_struct )); if ( !tmp ) { /* Pullup failed. The chain pointed to by *om has been freed */ return -1 ; } /* copy data from mbuf into header structure */ memcpy ( &my_header , tmp->om_data , sizeof ( struct my_header_struct ));","title":"Example"},{"location":"os/core_os/memory_pool/OS_MEMPOOL_BYTES/","text":"OS_MEMPOOL_BYTES OS_MEMPOOL_BYTES ( n , blksize ) Calculates how many bytes of memory is used by n number of elements, when individual element size is blksize bytes. Arguments Arguments Description n Number of elements blksize Size of an element is number of bytes Returned values The number of bytes used by the memory pool. Notes OS_MEMPOOL_BYTES is a macro and not a function. Example Here we allocate memory to be used as a pool. void *nffs_file_mem ; nffs_file_mem = malloc ( OS_MEMPOOL_BYTES ( nffs_config . nc_num_files , sizeof ( struct nffs_file ))); if ( nffs_file_mem == NULL ) { return FS_ENOMEM ; }","title":"OS_MEMPOOL_BYTES"},{"location":"os/core_os/memory_pool/OS_MEMPOOL_BYTES/#os_mempool_bytes","text":"OS_MEMPOOL_BYTES ( n , blksize ) Calculates how many bytes of memory is used by n number of elements, when individual element size is blksize bytes.","title":"OS_MEMPOOL_BYTES"},{"location":"os/core_os/memory_pool/OS_MEMPOOL_BYTES/#arguments","text":"Arguments Description n Number of elements blksize Size of an element is number of bytes","title":"Arguments"},{"location":"os/core_os/memory_pool/OS_MEMPOOL_BYTES/#returned-values","text":"The number of bytes used by the memory pool.","title":"Returned values"},{"location":"os/core_os/memory_pool/OS_MEMPOOL_BYTES/#notes","text":"OS_MEMPOOL_BYTES is a macro and not a function.","title":"Notes"},{"location":"os/core_os/memory_pool/OS_MEMPOOL_BYTES/#example","text":"Here we allocate memory to be used as a pool. void *nffs_file_mem ; nffs_file_mem = malloc ( OS_MEMPOOL_BYTES ( nffs_config . nc_num_files , sizeof ( struct nffs_file ))); if ( nffs_file_mem == NULL ) { return FS_ENOMEM ; }","title":"Example"},{"location":"os/core_os/memory_pool/OS_MEMPOOL_SIZE/","text":"OS_MEMPOOL_SIZE OS_MEMPOOL_SIZE ( n , blksize ) Calculates the number of os_membuf_t elements used by n blocks of size blksize bytes. Note that os_membuf_t is used so that memory blocks are aligned on OS_ALIGNMENT boundaries. The blksize variable is the minimum number of bytes required for each block; the actual block size is padded so that each block is aligned on OS_ALIGNMENT boundaries. Arguments Arguments Description n Number of elements blksize Size of an element is number of bytes Returned values The number of os_membuf_t elements used by the memory pool. Note that os_membuf_t is defined to be a unsigned, 32-bit integer when OS_ALIGNMENT is 4 and an unsigned, 64-bit integer when OS_ALIGNMENT is 8. Notes OS_MEMPOOL_SIZE is a macro and not a function. Example Here we define a memory buffer to be used by a memory pool using OS_MEMPOOL_SIZE #define NUM_BLOCKS (16) #define BLOCK_SIZE (32) os_membuf_t my_pool_memory [ OS_MEMPOOL_SIZE ( NUM_BLOCKS , BLOCK_SIZE )]","title":"OS_MEMPOOL_SIZE"},{"location":"os/core_os/memory_pool/OS_MEMPOOL_SIZE/#os_mempool_size","text":"OS_MEMPOOL_SIZE ( n , blksize ) Calculates the number of os_membuf_t elements used by n blocks of size blksize bytes. Note that os_membuf_t is used so that memory blocks are aligned on OS_ALIGNMENT boundaries. The blksize variable is the minimum number of bytes required for each block; the actual block size is padded so that each block is aligned on OS_ALIGNMENT boundaries.","title":"OS_MEMPOOL_SIZE"},{"location":"os/core_os/memory_pool/OS_MEMPOOL_SIZE/#arguments","text":"Arguments Description n Number of elements blksize Size of an element is number of bytes","title":"Arguments"},{"location":"os/core_os/memory_pool/OS_MEMPOOL_SIZE/#returned-values","text":"The number of os_membuf_t elements used by the memory pool. Note that os_membuf_t is defined to be a unsigned, 32-bit integer when OS_ALIGNMENT is 4 and an unsigned, 64-bit integer when OS_ALIGNMENT is 8.","title":"Returned values"},{"location":"os/core_os/memory_pool/OS_MEMPOOL_SIZE/#notes","text":"OS_MEMPOOL_SIZE is a macro and not a function.","title":"Notes"},{"location":"os/core_os/memory_pool/OS_MEMPOOL_SIZE/#example","text":"Here we define a memory buffer to be used by a memory pool using OS_MEMPOOL_SIZE #define NUM_BLOCKS (16) #define BLOCK_SIZE (32) os_membuf_t my_pool_memory [ OS_MEMPOOL_SIZE ( NUM_BLOCKS , BLOCK_SIZE )]","title":"Example"},{"location":"os/core_os/memory_pool/memory_pool/","text":"Memory Pools A memory pool is a collection of fixed sized elements called memory blocks. Generally, memory pools are used when the developer wants to allocate a certain amount of memory to a given feature. Unlike the heap, where a code module is at the mercy of other code modules to insure there is sufficient memory, memory pools can insure sufficient memory allocation. Description In order to create a memory pool the developer needs to do a few things. The first task is to define the memory pool itself. This is a data structure which contains information about the pool itself (i.e. number of blocks, size of the blocks, etc). struct os_mempool my_pool ; The next order of business is to allocate the memory used by the memory pool. This memory can either be statically allocated (i.e. a global variable) or dynamically allocated (i.e. from the heap). When determining the amount of memory required for the memory pool, simply multiplying the number of blocks by the size of each block is not sufficient as the OS may have alignment requirements. The alignment size definition is named OS_ALIGNMENT and can be found in os_arch.h as it is architecture specific. The memory block alignment is usually for efficiency but may be due to other reasons. Generally, blocks are aligned on 32-bit boundaries. Note that memory blocks must also be of sufficient size to hold a list pointer as this is needed to chain memory blocks on the free list. In order to simplify this for the user two macros have been provided: OS_MEMPOOL_BYTES(n, blksize) and OS_MEMPOOL_SIZE(n, blksize) . The first macro returns the number of bytes needed for the memory pool while the second returns the number of os_membuf_t elements required by the memory pool. The os_membuf_t type is used to guarantee that the memory buffer used by the memory pool is aligned on the correct boundary. Here are some examples. Note that if a custom malloc implementation is used it must guarantee that the memory buffer used by the pool is allocated on the correct boundary (i.e. OS_ALIGNMENT ). void *my_memory_buffer ; my_memory_buffer = malloc ( OS_MEMPOOL_BYTES ( NUM_BLOCKS , BLOCK_SIZE )); os_membuf_t my_memory_buffer [ OS_MEMPOOL_SIZE ( NUM_BLOCKS , BLOCK_SIZE )]; Now that the memory pool has been defined as well as the memory required for the memory blocks which make up the pool the user needs to initialize the memory pool by calling os_mempool_init . os_mempool_init ( &my_pool , NUM_BLOCKS , BLOCK_SIZE , my_memory_buffer , \"MyPool\" ); Once the memory pool has been initialized the developer can allocate memory blocks from the pool by calling os_memblock_get . When the memory block is no longer needed the memory can be freed by calling os_memblock_put . Data structures struct os_mempool { int mp_block_size ; int mp_num_blocks ; int mp_num_free ; int mp_min_free ; uint32_t mp_membuf_addr ; STAILQ_ENTRY ( os_mempool ) mp_list ; SLIST_HEAD (, os_memblock ); char *name ; }; struct os_mempool_info { int omi_block_size ; int omi_num_blocks ; int omi_num_free ; int omi_min_free ; char omi_name [ OS_MEMPOOL_INFO_NAME_LEN ]; }; Element Description mp_block_size Size of the memory blocks, in bytes. This is not the actual number of bytes used by each block; it is the requested size of each block. The actual memory block size will be aligned to OS_ALIGNMENT bytes mp_num_blocks Number of memory blocks in the pool mp_num_free Number of free blocks left mp_min_free Lowest number of free blocks seen mp_membuf_addr The address of the memory block. This is used to check that a valid memory block is being freed. mp_list List pointer to chain memory pools so they can be displayed by newt tools SLIST_HEAD(,os_memblock) List pointer to chain free memory blocks name Name for the memory block List of Functions/Macros The functions/macros available in mem_pool are: Function Description os_memblock_get Allocate an element from the memory pool. os_mempool_init Initializes the memory pool. os_memblock_put Releases previously allocated element back to the pool. os_mempool_info_get_next Retrieves memory pool information for the next memory pool. OS_MEMPOOL_BYTES Calculates how many bytes of memory is used by n number of elements, when individual element size is blksize bytes. OS_MEMPOOL_SIZE Calculates the number of os_membuf_t elements used by n blocks of size blksize bytes.","title":"toc"},{"location":"os/core_os/memory_pool/memory_pool/#memory-pools","text":"A memory pool is a collection of fixed sized elements called memory blocks. Generally, memory pools are used when the developer wants to allocate a certain amount of memory to a given feature. Unlike the heap, where a code module is at the mercy of other code modules to insure there is sufficient memory, memory pools can insure sufficient memory allocation.","title":"Memory Pools"},{"location":"os/core_os/memory_pool/memory_pool/#description","text":"In order to create a memory pool the developer needs to do a few things. The first task is to define the memory pool itself. This is a data structure which contains information about the pool itself (i.e. number of blocks, size of the blocks, etc). struct os_mempool my_pool ; The next order of business is to allocate the memory used by the memory pool. This memory can either be statically allocated (i.e. a global variable) or dynamically allocated (i.e. from the heap). When determining the amount of memory required for the memory pool, simply multiplying the number of blocks by the size of each block is not sufficient as the OS may have alignment requirements. The alignment size definition is named OS_ALIGNMENT and can be found in os_arch.h as it is architecture specific. The memory block alignment is usually for efficiency but may be due to other reasons. Generally, blocks are aligned on 32-bit boundaries. Note that memory blocks must also be of sufficient size to hold a list pointer as this is needed to chain memory blocks on the free list. In order to simplify this for the user two macros have been provided: OS_MEMPOOL_BYTES(n, blksize) and OS_MEMPOOL_SIZE(n, blksize) . The first macro returns the number of bytes needed for the memory pool while the second returns the number of os_membuf_t elements required by the memory pool. The os_membuf_t type is used to guarantee that the memory buffer used by the memory pool is aligned on the correct boundary. Here are some examples. Note that if a custom malloc implementation is used it must guarantee that the memory buffer used by the pool is allocated on the correct boundary (i.e. OS_ALIGNMENT ). void *my_memory_buffer ; my_memory_buffer = malloc ( OS_MEMPOOL_BYTES ( NUM_BLOCKS , BLOCK_SIZE )); os_membuf_t my_memory_buffer [ OS_MEMPOOL_SIZE ( NUM_BLOCKS , BLOCK_SIZE )]; Now that the memory pool has been defined as well as the memory required for the memory blocks which make up the pool the user needs to initialize the memory pool by calling os_mempool_init . os_mempool_init ( &my_pool , NUM_BLOCKS , BLOCK_SIZE , my_memory_buffer , \"MyPool\" ); Once the memory pool has been initialized the developer can allocate memory blocks from the pool by calling os_memblock_get . When the memory block is no longer needed the memory can be freed by calling os_memblock_put .","title":"Description"},{"location":"os/core_os/memory_pool/memory_pool/#data-structures","text":"struct os_mempool { int mp_block_size ; int mp_num_blocks ; int mp_num_free ; int mp_min_free ; uint32_t mp_membuf_addr ; STAILQ_ENTRY ( os_mempool ) mp_list ; SLIST_HEAD (, os_memblock ); char *name ; }; struct os_mempool_info { int omi_block_size ; int omi_num_blocks ; int omi_num_free ; int omi_min_free ; char omi_name [ OS_MEMPOOL_INFO_NAME_LEN ]; }; Element Description mp_block_size Size of the memory blocks, in bytes. This is not the actual number of bytes used by each block; it is the requested size of each block. The actual memory block size will be aligned to OS_ALIGNMENT bytes mp_num_blocks Number of memory blocks in the pool mp_num_free Number of free blocks left mp_min_free Lowest number of free blocks seen mp_membuf_addr The address of the memory block. This is used to check that a valid memory block is being freed. mp_list List pointer to chain memory pools so they can be displayed by newt tools SLIST_HEAD(,os_memblock) List pointer to chain free memory blocks name Name for the memory block","title":"Data structures"},{"location":"os/core_os/memory_pool/memory_pool/#list-of-functionsmacros","text":"The functions/macros available in mem_pool are: Function Description os_memblock_get Allocate an element from the memory pool. os_mempool_init Initializes the memory pool. os_memblock_put Releases previously allocated element back to the pool. os_mempool_info_get_next Retrieves memory pool information for the next memory pool. OS_MEMPOOL_BYTES Calculates how many bytes of memory is used by n number of elements, when individual element size is blksize bytes. OS_MEMPOOL_SIZE Calculates the number of os_membuf_t elements used by n blocks of size blksize bytes.","title":"List of Functions/Macros"},{"location":"os/core_os/memory_pool/os_memblock_get/","text":"os_memblock_get void *os_memblock_get ( struct os_mempool *mp ) Allocate an element from the memory pool. If successful, you'll get a pointer to allocated element. If there are no elements available, you'll get NULL as response. Arguments Arguments Description mp Pool where element is getting allocated from Returned values NULL : no elements available. : pointer to allocated element. Notes Example struct nffs_file *file ; file = os_memblock_get ( &nffs_file_pool ); if ( file != NULL ) { memset ( file , 0 , sizeof *file ); }","title":"os_memblock_get"},{"location":"os/core_os/memory_pool/os_memblock_get/#os_memblock_get","text":"void *os_memblock_get ( struct os_mempool *mp ) Allocate an element from the memory pool. If successful, you'll get a pointer to allocated element. If there are no elements available, you'll get NULL as response.","title":" os_memblock_get"},{"location":"os/core_os/memory_pool/os_memblock_get/#arguments","text":"Arguments Description mp Pool where element is getting allocated from","title":"Arguments"},{"location":"os/core_os/memory_pool/os_memblock_get/#returned-values","text":"NULL : no elements available. : pointer to allocated element.","title":"Returned values"},{"location":"os/core_os/memory_pool/os_memblock_get/#notes","text":"","title":"Notes"},{"location":"os/core_os/memory_pool/os_memblock_get/#example","text":"struct nffs_file *file ; file = os_memblock_get ( &nffs_file_pool ); if ( file != NULL ) { memset ( file , 0 , sizeof *file ); }","title":"Example"},{"location":"os/core_os/memory_pool/os_memblock_put/","text":"os_memblock_put os_error_t os_memblock_put ( struct os_mempool *mp , void *block_addr ) Releases previously allocated element back to the pool. Arguments Arguments Description mp Pointer to memory pool from which block was allocated block_addr Pointer to element getting freed Returned values OS_OK : operation was a success: OS_INVALID_PARAM : If either mp or block_addr were NULL , or the block being freed was outside the range of the memory buffer or not on a true block size boundary. Example if ( file != NULL ) { rc = os_memblock_put ( &nffs_file_pool , file ); if ( rc != 0 ) { /* Error freeing memory block */ } }","title":"os_memblock_put"},{"location":"os/core_os/memory_pool/os_memblock_put/#os_memblock_put","text":"os_error_t os_memblock_put ( struct os_mempool *mp , void *block_addr ) Releases previously allocated element back to the pool.","title":"os_memblock_put"},{"location":"os/core_os/memory_pool/os_memblock_put/#arguments","text":"Arguments Description mp Pointer to memory pool from which block was allocated block_addr Pointer to element getting freed","title":"Arguments"},{"location":"os/core_os/memory_pool/os_memblock_put/#returned-values","text":"OS_OK : operation was a success: OS_INVALID_PARAM : If either mp or block_addr were NULL , or the block being freed was outside the range of the memory buffer or not on a true block size boundary.","title":"Returned values"},{"location":"os/core_os/memory_pool/os_memblock_put/#example","text":"if ( file != NULL ) { rc = os_memblock_put ( &nffs_file_pool , file ); if ( rc != 0 ) { /* Error freeing memory block */ } }","title":"Example"},{"location":"os/core_os/memory_pool/os_mempool_info_get_next/","text":"os_mempool_info_get_next struct os_mempool * os_mempool_info_get_next ( struct os_mempool *mp , struct os_mempool_info *omi ) Populates the os_mempool_info structure pointed to by omi with memory pool information. The value of mp specifies the memory pool information to populate. If mp is NULL , it populates the information for the first memory pool on the memory pool list. If mp is not NULL, it populates the information for the next memory pool after mp . Arguments Arguments Description mp Pointer to the memory pool in the memory pool list from the previous os_mempool_info_get_next function call. The next memory pool after mp is populated. If mp is NULL, the first memory pool on the memory pool list is populated. omi Pointer to os_mempool_info structure where memory information will be stored. Returned values A pointer to the memory pool structure that was used to populate the memory pool information structure. NULL indicates mp is the last memory pool on the list and omi is not populated with memory pool information. Example shell_os_mpool_display_cmd ( int argc , char **argv ) { struct os_mempool *mp ; struct os_mempool_info omi ; char *name ; name = NULL ; found = 0 ; if ( argc > 1 && strcmp ( argv [ 1 ], \"\" )) { name = argv [ 1 ]; } console_printf ( \"Mempools: \\n\" ); mp = NULL ; console_printf ( \"%32s %5s %4s %4s %4s\\n\" , \"name\" , \"blksz\" , \"cnt\" , \"free\" , \"min\" ); while ( 1 ) { mp = o { _mempool_info_get_next ( mp , &omi ); if ( mp == NULL ) { break ; } if ( name ) { if ( strcmp ( name , omi . omi_name )) { continue ; } else { found = 1 ; } } console_printf ( \"%32s %5d %4d %4d %4d\\n\" , omi . omi_name , omi . omi_block_size , omi . omi_num_blocks , omi . omi_num_free , omi . omi_min_free ); } if ( name && !found ) { console_printf ( \"Couldn't find a memory pool with name %s\\n\" , name ); } return ( 0 ); }","title":"os_mempool_info_get_next"},{"location":"os/core_os/memory_pool/os_mempool_info_get_next/#os_mempool_info_get_next","text":"struct os_mempool * os_mempool_info_get_next ( struct os_mempool *mp , struct os_mempool_info *omi ) Populates the os_mempool_info structure pointed to by omi with memory pool information. The value of mp specifies the memory pool information to populate. If mp is NULL , it populates the information for the first memory pool on the memory pool list. If mp is not NULL, it populates the information for the next memory pool after mp .","title":" os_mempool_info_get_next"},{"location":"os/core_os/memory_pool/os_mempool_info_get_next/#arguments","text":"Arguments Description mp Pointer to the memory pool in the memory pool list from the previous os_mempool_info_get_next function call. The next memory pool after mp is populated. If mp is NULL, the first memory pool on the memory pool list is populated. omi Pointer to os_mempool_info structure where memory information will be stored.","title":"Arguments"},{"location":"os/core_os/memory_pool/os_mempool_info_get_next/#returned-values","text":"A pointer to the memory pool structure that was used to populate the memory pool information structure. NULL indicates mp is the last memory pool on the list and omi is not populated with memory pool information.","title":"Returned values"},{"location":"os/core_os/memory_pool/os_mempool_info_get_next/#example","text":"shell_os_mpool_display_cmd ( int argc , char **argv ) { struct os_mempool *mp ; struct os_mempool_info omi ; char *name ; name = NULL ; found = 0 ; if ( argc > 1 && strcmp ( argv [ 1 ], \"\" )) { name = argv [ 1 ]; } console_printf ( \"Mempools: \\n\" ); mp = NULL ; console_printf ( \"%32s %5s %4s %4s %4s\\n\" , \"name\" , \"blksz\" , \"cnt\" , \"free\" , \"min\" ); while ( 1 ) { mp = o { _mempool_info_get_next ( mp , &omi ); if ( mp == NULL ) { break ; } if ( name ) { if ( strcmp ( name , omi . omi_name )) { continue ; } else { found = 1 ; } } console_printf ( \"%32s %5d %4d %4d %4d\\n\" , omi . omi_name , omi . omi_block_size , omi . omi_num_blocks , omi . omi_num_free , omi . omi_min_free ); } if ( name && !found ) { console_printf ( \"Couldn't find a memory pool with name %s\\n\" , name ); } return ( 0 ); }","title":"Example"},{"location":"os/core_os/memory_pool/os_mempool_init/","text":"os_mempool_init os_error_t os_mempool_init ( struct os_mempool *mp , int blocks , int block_size , void *membuf , char *name ) Initializes the memory pool. Memory pointed to by membuf is divided into blocks number of elements of size OS_ALIGN(*block_size*) . The name is optional, and names the memory pool. It is assumed that the amount of memory pointed by membuf has at least OS_MEMPOOL_BYTES(blocks, block_size) number of bytes. name is not copied, so caller should make sure that the memory does not get reused. Arguments Arguments Description mp Memory pool being initialized blocks Number of elements in the pool block_size Minimum size of an individual element in pool membuf Backing store for the memory pool elements name Name of the memory pool Returned values OS_OK : operation was successful. OS_INVALID_PARAM : invalid parameters. Block count or block size was negative, or membuf or mp was NULL . OS_MEM_NOT_ALIGNED : membuf was not aligned on correct byte boundary. Notes Note that os_mempool_init() does not allocate backing storage; membuf has to be allocated by the caller. It's recommended that you use OS_MEMPOOL_BYTES() or OS_MEMPOOL_SIZE() to figure out how much memory to allocate for the pool. Example void *nffs_file_mem ; nffs_file_mem = malloc ( OS_MEMPOOL_BYTES ( nffs_config . nc_num_files , sizeof ( struct nffs_file ))); rc = os_mempool_init ( &nffs_file_pool , nffs_config . nc_num_files , sizeof ( struct nffs_file ), nffs_file_mem , \"nffs_file_pool\" ); if ( rc != 0 ) { /* Memory pool initialization failure */ }","title":"os_mempool_init"},{"location":"os/core_os/memory_pool/os_mempool_init/#os_mempool_init","text":"os_error_t os_mempool_init ( struct os_mempool *mp , int blocks , int block_size , void *membuf , char *name ) Initializes the memory pool. Memory pointed to by membuf is divided into blocks number of elements of size OS_ALIGN(*block_size*) . The name is optional, and names the memory pool. It is assumed that the amount of memory pointed by membuf has at least OS_MEMPOOL_BYTES(blocks, block_size) number of bytes. name is not copied, so caller should make sure that the memory does not get reused.","title":" os_mempool_init"},{"location":"os/core_os/memory_pool/os_mempool_init/#arguments","text":"Arguments Description mp Memory pool being initialized blocks Number of elements in the pool block_size Minimum size of an individual element in pool membuf Backing store for the memory pool elements name Name of the memory pool","title":"Arguments"},{"location":"os/core_os/memory_pool/os_mempool_init/#returned-values","text":"OS_OK : operation was successful. OS_INVALID_PARAM : invalid parameters. Block count or block size was negative, or membuf or mp was NULL . OS_MEM_NOT_ALIGNED : membuf was not aligned on correct byte boundary.","title":"Returned values"},{"location":"os/core_os/memory_pool/os_mempool_init/#notes","text":"Note that os_mempool_init() does not allocate backing storage; membuf has to be allocated by the caller. It's recommended that you use OS_MEMPOOL_BYTES() or OS_MEMPOOL_SIZE() to figure out how much memory to allocate for the pool.","title":"Notes"},{"location":"os/core_os/memory_pool/os_mempool_init/#example","text":"void *nffs_file_mem ; nffs_file_mem = malloc ( OS_MEMPOOL_BYTES ( nffs_config . nc_num_files , sizeof ( struct nffs_file ))); rc = os_mempool_init ( &nffs_file_pool , nffs_config . nc_num_files , sizeof ( struct nffs_file ), nffs_file_mem , \"nffs_file_pool\" ); if ( rc != 0 ) { /* Memory pool initialization failure */ }","title":"Example"},{"location":"os/core_os/mqueue/mqueue/","text":"Mqueue The mqueue construct allows a task to wake up when it receives data. Typically, this data is in the form of packets received over a network. A common networking stack operation is to put a packet on a queue and post an event to the task monitoring that queue. When the task handles the event, it processes each packet on the packet queue. Using Mqueue The following code sample demonstrates how to use an mqueue. In this example: packets are put on a receive queue a task processes each packet on the queue (increments a receive counter) Not shown in the code example is a call my_task_rx_data_func . Presumably, some other code will call this API. uint32_t pkts_rxd ; struct os_mqueue rxpkt_q ; struct os_eventq my_task_evq ; /** * Removes each packet from the receive queue and processes it. */ void process_rx_data_queue ( void ) { struct os_mbuf *om ; while (( om = os_mqueue_get ( &rxpkt_q )) != NULL ) { ++pkts_rxd ; os_mbuf_free_chain ( om ); } } /** * Called when a packet is received. */ int my_task_rx_data_func ( struct os_mbuf *om ) { int rc ; /* Enqueue the received packet and wake up the listening task. */ rc = os_mqueue_put ( &rxpkt_q , &my_task_evq , om ); if ( rc != 0 ) { return -1 ; } return 0 ; } void my_task_handler ( void *arg ) { struct os_event *ev ; struct os_callout_func *cf ; int rc ; /* Initialize eventq */ os_eventq_init ( &my_task_evq ); /* Initialize mqueue */ os_mqueue_init ( &rxpkt_q , NULL ); /* Process each event posted to our eventq. When there are no events to * process, sleep until one arrives. */ while ( 1 ) { os_eventq_run ( &my_task_evq ); } } Data Structures struct os_mqueue { STAILQ_HEAD (, os_mbuf_pkthdr ) mq_head ; struct os_event mq_ev ; }; List of Functions The functions available in Mqueue are: Function Description os_mqueue_init Initializes an mqueue. os_mqueue_get Retrieves a packet off an Mqueue. os_mqueue_put Adds a packet (i.e. packet header mbuf) to an mqueue.","title":"toc"},{"location":"os/core_os/mqueue/mqueue/#mqueue","text":"The mqueue construct allows a task to wake up when it receives data. Typically, this data is in the form of packets received over a network. A common networking stack operation is to put a packet on a queue and post an event to the task monitoring that queue. When the task handles the event, it processes each packet on the packet queue.","title":"Mqueue"},{"location":"os/core_os/mqueue/mqueue/#using-mqueue","text":"The following code sample demonstrates how to use an mqueue. In this example: packets are put on a receive queue a task processes each packet on the queue (increments a receive counter) Not shown in the code example is a call my_task_rx_data_func . Presumably, some other code will call this API. uint32_t pkts_rxd ; struct os_mqueue rxpkt_q ; struct os_eventq my_task_evq ; /** * Removes each packet from the receive queue and processes it. */ void process_rx_data_queue ( void ) { struct os_mbuf *om ; while (( om = os_mqueue_get ( &rxpkt_q )) != NULL ) { ++pkts_rxd ; os_mbuf_free_chain ( om ); } } /** * Called when a packet is received. */ int my_task_rx_data_func ( struct os_mbuf *om ) { int rc ; /* Enqueue the received packet and wake up the listening task. */ rc = os_mqueue_put ( &rxpkt_q , &my_task_evq , om ); if ( rc != 0 ) { return -1 ; } return 0 ; } void my_task_handler ( void *arg ) { struct os_event *ev ; struct os_callout_func *cf ; int rc ; /* Initialize eventq */ os_eventq_init ( &my_task_evq ); /* Initialize mqueue */ os_mqueue_init ( &rxpkt_q , NULL ); /* Process each event posted to our eventq. When there are no events to * process, sleep until one arrives. */ while ( 1 ) { os_eventq_run ( &my_task_evq ); } }","title":"Using Mqueue"},{"location":"os/core_os/mqueue/mqueue/#data-structures","text":"struct os_mqueue { STAILQ_HEAD (, os_mbuf_pkthdr ) mq_head ; struct os_event mq_ev ; };","title":"Data Structures"},{"location":"os/core_os/mqueue/mqueue/#list-of-functions","text":"The functions available in Mqueue are: Function Description os_mqueue_init Initializes an mqueue. os_mqueue_get Retrieves a packet off an Mqueue. os_mqueue_put Adds a packet (i.e. packet header mbuf) to an mqueue.","title":"List of Functions"},{"location":"os/core_os/mqueue/os_mqueue_get/","text":"os_mqueue_get struct os_mbuf *os_mqueue_get ( struct os_mqueue *mq ) Retrieves a packet off an mqueue. Returns a pointer to the mbuf at the head of the mbuf chain or NULL if no packets are on the queue. Arguments Arguments Description mq The mqueue to retrieve an mbuf from. Returned values The packet at the head of the queue or NULL if no packets are on the queue. Example uint32_t pkts_rxd ; struct os_mqueue rxpkt_q ; void process_rx_data_queue ( void ) { struct os_mbuf *om ; /* Drain all packets off queue and process them */ while (( om = os_mqueue_get ( &rxpkt_q )) != NULL ) { ++pkts_rxd ; os_mbuf_free_chain ( om ); } }","title":"os_mqueue_get"},{"location":"os/core_os/mqueue/os_mqueue_get/#os_mqueue_get","text":"struct os_mbuf *os_mqueue_get ( struct os_mqueue *mq ) Retrieves a packet off an mqueue. Returns a pointer to the mbuf at the head of the mbuf chain or NULL if no packets are on the queue.","title":"os_mqueue_get"},{"location":"os/core_os/mqueue/os_mqueue_get/#arguments","text":"Arguments Description mq The mqueue to retrieve an mbuf from.","title":"Arguments"},{"location":"os/core_os/mqueue/os_mqueue_get/#returned-values","text":"The packet at the head of the queue or NULL if no packets are on the queue.","title":"Returned values"},{"location":"os/core_os/mqueue/os_mqueue_get/#example","text":"uint32_t pkts_rxd ; struct os_mqueue rxpkt_q ; void process_rx_data_queue ( void ) { struct os_mbuf *om ; /* Drain all packets off queue and process them */ while (( om = os_mqueue_get ( &rxpkt_q )) != NULL ) { ++pkts_rxd ; os_mbuf_free_chain ( om ); } }","title":"Example"},{"location":"os/core_os/mqueue/os_mqueue_init/","text":"os_mqueue_init int os_mqueue_init ( struct os_mqueue *mq , os_event_fn *ev_cb , void *arg ) Initializes an mqueue. An mqueue is a queue of mbufs that ties to a particular task's event queue. Mqueues form a helper API around a common paradigm: wait on an event queue until at least one packet is available, then process a queue of packets. Arguments Arguments Description mq The mqueue to initialize ev_cb The callback to associate with the mqeueue event. Typically, this callback pulls each packet off the mqueue and processes them. arg The argument to associate with the mqueue event. @return 0 on success, non-zero on failure. Initializes an mqueue. Sets the event argument in the os event of the mqueue to arg . Arguments Arguments Description mq Pointer to a mqueue structure arg Event argument Returned values 0: success. All other values indicate an error Example /* Event callback to execute when a packet is received. */ extern void process_rx_data_queue ( void ); /* Declare mqueue */ struct os_mqueue rxpkt_q ; /* Initialize mqueue */ os_mqueue_init ( &rxpkt_q , process_rx_data_queue , NULL );","title":"os_mqueue_init"},{"location":"os/core_os/mqueue/os_mqueue_init/#os_mqueue_init","text":"int os_mqueue_init ( struct os_mqueue *mq , os_event_fn *ev_cb , void *arg ) Initializes an mqueue. An mqueue is a queue of mbufs that ties to a particular task's event queue. Mqueues form a helper API around a common paradigm: wait on an event queue until at least one packet is available, then process a queue of packets.","title":"os_mqueue_init"},{"location":"os/core_os/mqueue/os_mqueue_init/#arguments","text":"Arguments Description mq The mqueue to initialize ev_cb The callback to associate with the mqeueue event. Typically, this callback pulls each packet off the mqueue and processes them. arg The argument to associate with the mqueue event. @return 0 on success, non-zero on failure. Initializes an mqueue. Sets the event argument in the os event of the mqueue to arg .","title":"Arguments"},{"location":"os/core_os/mqueue/os_mqueue_init/#arguments_1","text":"Arguments Description mq Pointer to a mqueue structure arg Event argument","title":"Arguments"},{"location":"os/core_os/mqueue/os_mqueue_init/#returned-values","text":"0: success. All other values indicate an error","title":"Returned values"},{"location":"os/core_os/mqueue/os_mqueue_init/#example","text":"/* Event callback to execute when a packet is received. */ extern void process_rx_data_queue ( void ); /* Declare mqueue */ struct os_mqueue rxpkt_q ; /* Initialize mqueue */ os_mqueue_init ( &rxpkt_q , process_rx_data_queue , NULL );","title":"Example"},{"location":"os/core_os/mqueue/os_mqueue_put/","text":"os_mqueue_put int os_mqueue_put ( struct os_mqueue *mq , struct os_eventq *evq , struct os_mbuf *m ) Adds a packet (i.e. packet header mbuf) to an mqueue. The event associated with the mqueue gets posted to the specified eventq. Arguments Arguments Description mq The mbuf queue to append the mbuf to. evq The event queue to post an event to. m The mbuf to append to the mbuf queue. Returned values 0: success OS_EINVAL : the mbuf is not a packet header mbuf. Example int my_task_rx_data_func ( struct os_mbuf *om ) { int rc ; rc = os_mqueue_put ( &rxpkt_q , &my_task_evq , om ); if ( rc != 0 ) { return -1 ; } return 0 ; }","title":"os_mqueue_put"},{"location":"os/core_os/mqueue/os_mqueue_put/#os_mqueue_put","text":"int os_mqueue_put ( struct os_mqueue *mq , struct os_eventq *evq , struct os_mbuf *m ) Adds a packet (i.e. packet header mbuf) to an mqueue. The event associated with the mqueue gets posted to the specified eventq.","title":"os_mqueue_put"},{"location":"os/core_os/mqueue/os_mqueue_put/#arguments","text":"Arguments Description mq The mbuf queue to append the mbuf to. evq The event queue to post an event to. m The mbuf to append to the mbuf queue.","title":"Arguments"},{"location":"os/core_os/mqueue/os_mqueue_put/#returned-values","text":"0: success OS_EINVAL : the mbuf is not a packet header mbuf.","title":"Returned values"},{"location":"os/core_os/mqueue/os_mqueue_put/#example","text":"int my_task_rx_data_func ( struct os_mbuf *om ) { int rc ; rc = os_mqueue_put ( &rxpkt_q , &my_task_evq , om ); if ( rc != 0 ) { return -1 ; } return 0 ; }","title":"Example"},{"location":"os/core_os/msys/msys/","text":"Msys Msys stands for \"system mbufs\" and is a set of APIs built on top of the mbuf code. The basic idea behind msys is the following. The developer can create different size mbuf pools and register them with msys. The application then allocates mbufs using the msys API (as opposed to the mbuf API). The msys code will choose the mbuf pool with the smallest mbufs that can accommodate the requested size. Let us walk through an example where the user registers three mbuf pools with msys: one with 32 byte mbufs, one with 256 and one with 2048. If the user requests an mbuf with 10 bytes, the 32-byte mbuf pool is used. If the request is for 33 bytes the 256 byte mbuf pool is used. If an mbuf data size is requested that is larger than any of the pools (say, 4000 bytes) the largest pool is used. While this behaviour may not be optimal in all cases that is the currently implemented behaviour. All this means is that the user is not guaranteed that a single mbuf can hold the requested data. The msys code will not allocate an mbuf from a larger pool if the chosen mbuf pool is empty. Similarly, the msys code will not chain together a number of smaller mbufs to accommodate the requested size. While this behaviour may change in future implementations the current code will simply return NULL . Using the above example, say the user requests 250 bytes. The msys code chooses the appropriate pool (i.e. the 256 byte mbuf pool) and attempts to allocate an mbuf from that pool. If that pool is empty, NULL is returned even though the 32 and 2048 byte pools are not empty. Note that no added descriptions on how to use the msys API are presented here (other than in the API descriptions themselves) as the msys API is used in exactly the same manner as the mbuf API. The only difference is that mbuf pools are added to msys by calling os_msys_register(). List of Functions The functions available in msys are: Function Description os_msys_get Retrieve an mbuf from the system mbuf pools with the given number of bytes available in the mbuf. os_msys_get_pkthdr Retrieve a packet header mbuf from the system mbuf pools with the given number of bytes available for the user header in the mbuf. os_msys_register Register an mbuf pool for use as a system mbuf pool. os_msys_reset Resets msys module.","title":"toc"},{"location":"os/core_os/msys/msys/#msys","text":"Msys stands for \"system mbufs\" and is a set of APIs built on top of the mbuf code. The basic idea behind msys is the following. The developer can create different size mbuf pools and register them with msys. The application then allocates mbufs using the msys API (as opposed to the mbuf API). The msys code will choose the mbuf pool with the smallest mbufs that can accommodate the requested size. Let us walk through an example where the user registers three mbuf pools with msys: one with 32 byte mbufs, one with 256 and one with 2048. If the user requests an mbuf with 10 bytes, the 32-byte mbuf pool is used. If the request is for 33 bytes the 256 byte mbuf pool is used. If an mbuf data size is requested that is larger than any of the pools (say, 4000 bytes) the largest pool is used. While this behaviour may not be optimal in all cases that is the currently implemented behaviour. All this means is that the user is not guaranteed that a single mbuf can hold the requested data. The msys code will not allocate an mbuf from a larger pool if the chosen mbuf pool is empty. Similarly, the msys code will not chain together a number of smaller mbufs to accommodate the requested size. While this behaviour may change in future implementations the current code will simply return NULL . Using the above example, say the user requests 250 bytes. The msys code chooses the appropriate pool (i.e. the 256 byte mbuf pool) and attempts to allocate an mbuf from that pool. If that pool is empty, NULL is returned even though the 32 and 2048 byte pools are not empty. Note that no added descriptions on how to use the msys API are presented here (other than in the API descriptions themselves) as the msys API is used in exactly the same manner as the mbuf API. The only difference is that mbuf pools are added to msys by calling os_msys_register().","title":"Msys"},{"location":"os/core_os/msys/msys/#list-of-functions","text":"The functions available in msys are: Function Description os_msys_get Retrieve an mbuf from the system mbuf pools with the given number of bytes available in the mbuf. os_msys_get_pkthdr Retrieve a packet header mbuf from the system mbuf pools with the given number of bytes available for the user header in the mbuf. os_msys_register Register an mbuf pool for use as a system mbuf pool. os_msys_reset Resets msys module.","title":"List of Functions"},{"location":"os/core_os/msys/os_msys_get/","text":"os_msys_get struct os_mbuf *os_msys_get ( uint16_t dsize , uint16_t leadingspace ) Retrieve an mbuf from the system mbuf pools with leadingspace bytes available in the mbuf. Arguments Arguments Description dsize Minimum requested size of mbuf. Actual mbuf allocated may not accommodate dsize leadingspace Number of bytes for leading space in mbuf (space at start of mbuf) Returned values Pointer to mbuf or NULL if no mbufs were available. Notes As described in the overview section, os_msys_get() may return an mbuf that is smaller than dsize , meaning that the mbuf user data buffer does not have enough contiguous space to hold dsize bytes. This API will not return an mbuf from a larger mbuf pool if the appropriate msys mbuf pool is empty. See the overview for more information. Example struct os_mbuf *om ; /* Allocate an mbuf with hopefully at least 100 bytes in its user data buffer */ om = os_msys_get ( 100 , 0 ); if ( !om ) { /* No mbufs available. */ return -1 ; } }","title":"os_msys_get"},{"location":"os/core_os/msys/os_msys_get/#os_msys_get","text":"struct os_mbuf *os_msys_get ( uint16_t dsize , uint16_t leadingspace ) Retrieve an mbuf from the system mbuf pools with leadingspace bytes available in the mbuf.","title":"os_msys_get"},{"location":"os/core_os/msys/os_msys_get/#arguments","text":"Arguments Description dsize Minimum requested size of mbuf. Actual mbuf allocated may not accommodate dsize leadingspace Number of bytes for leading space in mbuf (space at start of mbuf)","title":"Arguments"},{"location":"os/core_os/msys/os_msys_get/#returned-values","text":"Pointer to mbuf or NULL if no mbufs were available.","title":"Returned values"},{"location":"os/core_os/msys/os_msys_get/#notes","text":"As described in the overview section, os_msys_get() may return an mbuf that is smaller than dsize , meaning that the mbuf user data buffer does not have enough contiguous space to hold dsize bytes. This API will not return an mbuf from a larger mbuf pool if the appropriate msys mbuf pool is empty. See the overview for more information.","title":"Notes"},{"location":"os/core_os/msys/os_msys_get/#example","text":"struct os_mbuf *om ; /* Allocate an mbuf with hopefully at least 100 bytes in its user data buffer */ om = os_msys_get ( 100 , 0 ); if ( !om ) { /* No mbufs available. */ return -1 ; } }","title":"Example"},{"location":"os/core_os/msys/os_msys_get_pkthdr/","text":"os_msys_get_pkthdr struct os_mbuf *os_msys_get_pkthdr ( uint16_t dsize , uint16_t user_hdr_len ) Retrieve a packet header mbuf from the system mbuf pools with user_hdr_len bytes available for the user header in the mbuf. Arguments Arguments Description dsize Minimum requested size of mbuf. Actual mbuf allocated may not accommodate dsize user_hdr_len Size, in of bytes, of user header in the mbuf Returned values Pointer to mbuf or NULL if no mbufs were available. Notes The same notes apply to this API as to os_msys_get() . Example struct os_mbuf *om ; struct my_user_hdr_struct my_usr_hdr ; /* * Allocate an mbuf with hopefully at least 100 bytes in its user data buffer * and that has a user header of size sizeof(struct my_user_hdr_struct) */ om = os_msys_get_pkthdr ( 100 , sizeof ( struct my_user_hdr_struct )); if ( !om ) { /* No mbufs available. */ return -1 ; } }","title":"os_msys_get_pkthdr"},{"location":"os/core_os/msys/os_msys_get_pkthdr/#os_msys_get_pkthdr","text":"struct os_mbuf *os_msys_get_pkthdr ( uint16_t dsize , uint16_t user_hdr_len ) Retrieve a packet header mbuf from the system mbuf pools with user_hdr_len bytes available for the user header in the mbuf.","title":"os_msys_get_pkthdr"},{"location":"os/core_os/msys/os_msys_get_pkthdr/#arguments","text":"Arguments Description dsize Minimum requested size of mbuf. Actual mbuf allocated may not accommodate dsize user_hdr_len Size, in of bytes, of user header in the mbuf","title":"Arguments"},{"location":"os/core_os/msys/os_msys_get_pkthdr/#returned-values","text":"Pointer to mbuf or NULL if no mbufs were available.","title":"Returned values"},{"location":"os/core_os/msys/os_msys_get_pkthdr/#notes","text":"The same notes apply to this API as to os_msys_get() .","title":"Notes"},{"location":"os/core_os/msys/os_msys_get_pkthdr/#example","text":"struct os_mbuf *om ; struct my_user_hdr_struct my_usr_hdr ; /* * Allocate an mbuf with hopefully at least 100 bytes in its user data buffer * and that has a user header of size sizeof(struct my_user_hdr_struct) */ om = os_msys_get_pkthdr ( 100 , sizeof ( struct my_user_hdr_struct )); if ( !om ) { /* No mbufs available. */ return -1 ; } }","title":"Example"},{"location":"os/core_os/msys/os_msys_register/","text":"os_msys_register int os_msys_register ( struct os_mbuf_pool *new_pool ) Register an mbuf pool for use as a system mbuf pool. The pool should be initialized prior to registration. Arguments Arguments Description new_pool Pointer to mbuf pool to add to system mbuf pools Returned values 0 on success; all other values indicate an error. Example rc = os_msys_register ( &g_mbuf_pool ); assert ( rc == 0 );","title":"os_msys_register"},{"location":"os/core_os/msys/os_msys_register/#os_msys_register","text":"int os_msys_register ( struct os_mbuf_pool *new_pool ) Register an mbuf pool for use as a system mbuf pool. The pool should be initialized prior to registration.","title":"os_msys_register"},{"location":"os/core_os/msys/os_msys_register/#arguments","text":"Arguments Description new_pool Pointer to mbuf pool to add to system mbuf pools","title":"Arguments"},{"location":"os/core_os/msys/os_msys_register/#returned-values","text":"0 on success; all other values indicate an error.","title":"Returned values"},{"location":"os/core_os/msys/os_msys_register/#example","text":"rc = os_msys_register ( &g_mbuf_pool ); assert ( rc == 0 );","title":"Example"},{"location":"os/core_os/msys/os_msys_reset/","text":"os_msys_reset void os_msys_reset ( void ) Resets msys module. This de-registers all pools from msys but does nothing to the pools themselves (they still exist as mbuf pools). Arguments None Returned values None Example os_msys_reset ();","title":"os_msys_reset"},{"location":"os/core_os/msys/os_msys_reset/#os_msys_reset","text":"void os_msys_reset ( void ) Resets msys module. This de-registers all pools from msys but does nothing to the pools themselves (they still exist as mbuf pools).","title":"os_msys_reset"},{"location":"os/core_os/msys/os_msys_reset/#arguments","text":"None","title":"Arguments"},{"location":"os/core_os/msys/os_msys_reset/#returned-values","text":"None","title":"Returned values"},{"location":"os/core_os/msys/os_msys_reset/#example","text":"os_msys_reset ();","title":"Example"},{"location":"os/core_os/mutex/mutex/","text":"Mutex Mutex is short for \"mutual exclusion\"; a mutex provides mutually exclusive access to a shared resource. A mutex provides priority inheritance in order to prevent priority inversion . Priority inversion occurs when a higher priority task is waiting on a resource owned by a lower priority task. Using a mutex, the lower priority task will inherit the highest priority of any task waiting on the mutex. Description The first order of business when using a mutex is to declare the mutex globally. The mutex needs to be initialized before it is used (see the examples). It is generally a good idea to initialize the mutex before tasks start running in order to avoid a task possibly using the mutex before it is initialized. When a task wants exclusive access to a shared resource it needs to obtain the mutex by calling os_mutex_pend . If the mutex is currently owned by a different task (a lower priority task), the requesting task will be put to sleep and the owners priority will be elevated to the priority of the requesting task. Note that multiple tasks can request ownership and the current owner is elevated to the highest priority of any task waitin on the mutex. When the task is done using the shared resource, it needs to release the mutex by called os_mutex_release . There needs to be one release per call to pend. Note that nested calls to os_mutex_pend are allowed but there needs to be one release per pend. The following example will illustrate how priority inheritance works. In this example, the task number is the same as its priority. Remember that the lower the number, the higher the priority (i.e. priority 0 is higher priority than priority 1). Suppose that task 5 gets ownership of a mutex but is preempted by task 4. Task 4 attempts to gain ownership of the mutex but cannot as it is owned by task 5. Task 4 is put to sleep and task 5 is temporarily raised to priority 4. Before task 5 can release the mutex, task 3 runs and attempts to acquire the mutex. At this point, both task 3 and task 4 are waiting on the mutex (sleeping). Task 5 now runs at priority 3 (the highest priority of all the tasks waiting on the mutex). When task 5 finally releases the mutex it will be preempted as two higher priority tasks are waiting for it. Note that when multiple tasks are waiting on a mutex owned by another task, once the mutex is released the highest priority task waiting on the mutex is run. Data structures struct os_mutex { SLIST_HEAD (, os_task ) mu_head ; uint8_t _pad ; uint8_t mu_prio ; uint16_t mu_level ; struct os_task *mu_owner ; }; Element Description mu_head Queue head for list of tasks waiting on mutex _pad Padding mu_prio Default priority of owner of mutex. Used to reset priority of task when mutex released mu_level Call nesting level (for nested calls) mu_owner Pointer to task structure which owns mutex List of Functions The functions available in this OS feature are: Function Description os_mutex_init Initialize the mutex. Must be called before the mutex can be used. os_mutex_pend Acquire ownership of a mutex. os_mutex_release Release ownership of a mutex.","title":"toc"},{"location":"os/core_os/mutex/mutex/#mutex","text":"Mutex is short for \"mutual exclusion\"; a mutex provides mutually exclusive access to a shared resource. A mutex provides priority inheritance in order to prevent priority inversion . Priority inversion occurs when a higher priority task is waiting on a resource owned by a lower priority task. Using a mutex, the lower priority task will inherit the highest priority of any task waiting on the mutex.","title":"Mutex"},{"location":"os/core_os/mutex/mutex/#description","text":"The first order of business when using a mutex is to declare the mutex globally. The mutex needs to be initialized before it is used (see the examples). It is generally a good idea to initialize the mutex before tasks start running in order to avoid a task possibly using the mutex before it is initialized. When a task wants exclusive access to a shared resource it needs to obtain the mutex by calling os_mutex_pend . If the mutex is currently owned by a different task (a lower priority task), the requesting task will be put to sleep and the owners priority will be elevated to the priority of the requesting task. Note that multiple tasks can request ownership and the current owner is elevated to the highest priority of any task waitin on the mutex. When the task is done using the shared resource, it needs to release the mutex by called os_mutex_release . There needs to be one release per call to pend. Note that nested calls to os_mutex_pend are allowed but there needs to be one release per pend. The following example will illustrate how priority inheritance works. In this example, the task number is the same as its priority. Remember that the lower the number, the higher the priority (i.e. priority 0 is higher priority than priority 1). Suppose that task 5 gets ownership of a mutex but is preempted by task 4. Task 4 attempts to gain ownership of the mutex but cannot as it is owned by task 5. Task 4 is put to sleep and task 5 is temporarily raised to priority 4. Before task 5 can release the mutex, task 3 runs and attempts to acquire the mutex. At this point, both task 3 and task 4 are waiting on the mutex (sleeping). Task 5 now runs at priority 3 (the highest priority of all the tasks waiting on the mutex). When task 5 finally releases the mutex it will be preempted as two higher priority tasks are waiting for it. Note that when multiple tasks are waiting on a mutex owned by another task, once the mutex is released the highest priority task waiting on the mutex is run.","title":"Description"},{"location":"os/core_os/mutex/mutex/#data-structures","text":"struct os_mutex { SLIST_HEAD (, os_task ) mu_head ; uint8_t _pad ; uint8_t mu_prio ; uint16_t mu_level ; struct os_task *mu_owner ; }; Element Description mu_head Queue head for list of tasks waiting on mutex _pad Padding mu_prio Default priority of owner of mutex. Used to reset priority of task when mutex released mu_level Call nesting level (for nested calls) mu_owner Pointer to task structure which owns mutex","title":"Data structures"},{"location":"os/core_os/mutex/mutex/#list-of-functions","text":"The functions available in this OS feature are: Function Description os_mutex_init Initialize the mutex. Must be called before the mutex can be used. os_mutex_pend Acquire ownership of a mutex. os_mutex_release Release ownership of a mutex.","title":"List of Functions"},{"location":"os/core_os/mutex/os_mutex_init/","text":"os_mutex_init os_error_t os_mutex_init ( struct os_mutex *mu ) Initialize the mutex. Must be called before the mutex can be used. Arguments Arguments Description *mu Pointer to mutex Returned values OS_INVALID_PARM : returned when *mu is NULL on entry. OS_OK : mutex initialized successfully. Notes Example struct os_mutex g_mutex1 ; os_error_t err ; err = os_mutex_init ( &g_mutex1 ); assert ( err == OS_OK );","title":"os_mutex_init"},{"location":"os/core_os/mutex/os_mutex_init/#os_mutex_init","text":"os_error_t os_mutex_init ( struct os_mutex *mu ) Initialize the mutex. Must be called before the mutex can be used.","title":"os_mutex_init"},{"location":"os/core_os/mutex/os_mutex_init/#arguments","text":"Arguments Description *mu Pointer to mutex","title":"Arguments"},{"location":"os/core_os/mutex/os_mutex_init/#returned-values","text":"OS_INVALID_PARM : returned when *mu is NULL on entry. OS_OK : mutex initialized successfully.","title":"Returned values"},{"location":"os/core_os/mutex/os_mutex_init/#notes","text":"","title":"Notes"},{"location":"os/core_os/mutex/os_mutex_init/#example","text":"struct os_mutex g_mutex1 ; os_error_t err ; err = os_mutex_init ( &g_mutex1 ); assert ( err == OS_OK );","title":"Example"},{"location":"os/core_os/mutex/os_mutex_pend/","text":"os_mutex_pend os_error_t os_mutex_pend ( struct os_mutex *mu , uint32_t timeout ) Acquire ownership of a mutex. Arguments Arguments Description *mu Pointer to mutex timeout Timeout, in os ticks. A value of 0 means no timeout. A value of 0xFFFFFFFF means to wait forever. Returned values OS_INVALID_PARM : returned when *mu is NULL on entry. OS_OK : mutex was successfully acquired. OS_TIMEOUT : the mutex was not available within the timeout specified. OS_NOT_STARTED : Attempt to release a mutex before the os has been started. Notes If the mutex is owned by another task and the timeout is 0 the function returns immediately with the error code OS_TIMEOUT . The calling task does not own the mutex when this occurs. Example struct os_mutex g_mutex1 ; os_error_t err ; err = os_mutex_pend ( &g_mutex1 , 0 ); assert ( err == OS_OK ); /* Perform operations requiring exclusive access */ err = os_mutex_release ( &g_mutex1 ); assert ( err == OS_OK );","title":"os_mutex_pend"},{"location":"os/core_os/mutex/os_mutex_pend/#os_mutex_pend","text":"os_error_t os_mutex_pend ( struct os_mutex *mu , uint32_t timeout ) Acquire ownership of a mutex.","title":"os_mutex_pend "},{"location":"os/core_os/mutex/os_mutex_pend/#arguments","text":"Arguments Description *mu Pointer to mutex timeout Timeout, in os ticks. A value of 0 means no timeout. A value of 0xFFFFFFFF means to wait forever.","title":"Arguments"},{"location":"os/core_os/mutex/os_mutex_pend/#returned-values","text":"OS_INVALID_PARM : returned when *mu is NULL on entry. OS_OK : mutex was successfully acquired. OS_TIMEOUT : the mutex was not available within the timeout specified. OS_NOT_STARTED : Attempt to release a mutex before the os has been started.","title":"Returned values"},{"location":"os/core_os/mutex/os_mutex_pend/#notes","text":"If the mutex is owned by another task and the timeout is 0 the function returns immediately with the error code OS_TIMEOUT . The calling task does not own the mutex when this occurs.","title":"Notes"},{"location":"os/core_os/mutex/os_mutex_pend/#example","text":"struct os_mutex g_mutex1 ; os_error_t err ; err = os_mutex_pend ( &g_mutex1 , 0 ); assert ( err == OS_OK ); /* Perform operations requiring exclusive access */ err = os_mutex_release ( &g_mutex1 ); assert ( err == OS_OK );","title":"Example"},{"location":"os/core_os/mutex/os_mutex_release/","text":"os_mutex_release os_error_t os_mutex_release ( struct os_mutex *mu ) Release ownership of a mutex Arguments Arguments Description *mu Pointer to mutex Returned values OS_INVALID_PARM : returned when *mu is NULL on entry. OS_OK : mutex initialized successfully. OS_BAD_MUTEX : The mutex was not owned by the task attempting to release it. OS_NOT_STARTED : Attempt to release a mutex before the os has been started. Example struct os_mutex g_mutex1 ; os_error_t err ; err = os_mutex_pend ( &g_mutex1 , 0 ); assert ( err == OS_OK ); /* Perform operations requiring exclusive access */ err = os_mutex_release ( &g_mutex1 ); assert ( err == OS_OK );","title":"os_mutex_release"},{"location":"os/core_os/mutex/os_mutex_release/#os_mutex_release","text":"os_error_t os_mutex_release ( struct os_mutex *mu ) Release ownership of a mutex","title":"os_mutex_release"},{"location":"os/core_os/mutex/os_mutex_release/#arguments","text":"Arguments Description *mu Pointer to mutex","title":"Arguments"},{"location":"os/core_os/mutex/os_mutex_release/#returned-values","text":"OS_INVALID_PARM : returned when *mu is NULL on entry. OS_OK : mutex initialized successfully. OS_BAD_MUTEX : The mutex was not owned by the task attempting to release it. OS_NOT_STARTED : Attempt to release a mutex before the os has been started.","title":"Returned values"},{"location":"os/core_os/mutex/os_mutex_release/#example","text":"struct os_mutex g_mutex1 ; os_error_t err ; err = os_mutex_pend ( &g_mutex1 , 0 ); assert ( err == OS_OK ); /* Perform operations requiring exclusive access */ err = os_mutex_release ( &g_mutex1 ); assert ( err == OS_OK );","title":"Example"},{"location":"os/core_os/porting/port_bsp/","text":"Create a BSP for your Target Introduction If you are using a board or system not currently supported by Mynewt, you will need to create a BSP for the new target. If another similar BSP exists it is recommended to copy that BSP as a starting point. For example, if another BSP exists using the same MCU, start with a copy of that BSP. Either way, this document describes the steps necessary to create a new BSP from scratch. Keep your Reference Documents handy To build a proper BSP, you will typically need the following: The datasheet for the MCU you have chosen The schematic of your board The information on the CPU core within your MCU if it is not included in your MCU documentation This Mynewt documentation Name your BSP Select a name for your BSP. For the remainder of this document, we'll assume the bsp is named myboard . In general its best to select a name that describes the board/system you are creating. Create a BSP directory Create a directory hw/bsp/myboard using the name chosen above. Within this BSP directory, create the following subdirectories: include include/bsp src Create a Target using Mynewt Create a newt target for your test project for the BSP. To learn how to create a target, see this howto Tutorial . Once you are familiar with creating targets, move on below to create a target to use to test your BSP. It is recommended that you use a simple project like blinky to minimize the time to get a working Mynewt system. For this document, we will assume the target is called myboard_blinky and uses project blinky . Set the bsp of the project to /hw/bsp/myboard . While creating your target, you will need to specify your arch and compiler . If your platform requires an architecture or compiler that are not defined in Mynewt, you will need to add them first. To add a CPU architecture see CPU Porting . When this is complete, your target may look similar to this. $ newt target show myboard_blinky arch=cortex_m0 bsp=hw/bsp/myboard compiler=arm-none-eabi-m0 compiler_def=debug name=myboard_blinky project=blinky Create Required Files For Compilation Create the following files within the BSP directory tree. For now, they can be empty files. We will fill them out one at a time. File Path Name Description LICENSE A File to present the source license for your BSP README.md A markdown file to write documentation for your BSP pkg.yml A package file to describe your BSP contents include/bsp/bsp.h A header file to include definitions required by system from the BSP include/bsp/bsp_sysid.h A header file to enumerate the devices in your BSP src/os_bsp.c A C source file to provide functions required by the OS from your BSP src/sbrk.c A C source file to memory from your heap to the OS src/libc_stubs.c A C source file to provide stubs/methods required by libc myboard.ld A linker script to provide the memory map for your linked code Optionally, create these files as necessary to provide all functionality from Mynewt. File Path Name Description myboard_boot.ld A linker script to provide the memory map for your bootloader myboard_download.sh A bash script to download code into your platform myboard_debug.sh A bash script to intiate a gdb session with your platform src/hal_bsp.c A C source file to provide functions required by the HAL from your BSP Fill Out your Package File Edit the package file to describe your BSP. The package file must contain: pkg.name: \"hw/bsp/myboard\" pkg.linkerscript: \"myboard.ld\" Attribute Description pkg.name The name of your bsp package pkg.linkerscript The linker script that controls the memory placement of the compiled code sections from the Mynewt OS and your applications. The linker script is a key component of the BSP and specifies where each section of code and data are stored within your CPU which can vary with the BSP depending on your chosen memory layout. For a tutorial on writing linker scripts, see Create or Copy Linker Script(s) . The package file typically contains: pkg.linkerscript.bootloader.OVERWRITE: \"myboard_boot.ld\" pkg.downloadscript: \"myboard_download.sh\" pkg.debugscript: \"myboard_debug.sh\" pkg.deps: - hw/mcu/mymcu/variant where mymcu/variant should be replaced with the specific MCU and variant used in your design. The following table describes additional attributes relevant to the BSP pkg.yml file. Attribute Description pkg.linkerscript.bootloader.OVERWRITE A special linker for creating a bootloader for Mynewt pkg.downloadscript A script that can download a flash image into your target platform pkg.debugscript A script that can run the GDB debugger on your board pkg.deps Any dependencies on your BSP The BSP will invariably depend upon an MCU (in this sample it's hw/mcu/mymcu/variant ) since the Mynewt OS runs on an MCU within your target. If your MCU is not supported by Mynewt, see MCU Porting for details on how to create a new MCU in Mynewt. The package file may also contain: pkg.cflags: -D__MY_SPECIAL_BSP_OPTIONS_ pkg.deps: - libs/cmsis-core Attribute Description pkg.cflags Any specific compiler flags for your bsp pkg.deps Any other libraries that may be required. Some architectures (like ARM) have special libraries to make BSP creation easier. Create or Copy Linker Script It's probably best to start with a linker script from another BSP using the same MCU. If this is not available, consult your MCU documentation and library samples to find a linker script to start with. Typically, a linker script has to specify the following sections for code: .text -- the location and alignment of the memory section to store your code .data -- the location and alignment of the memory section to store initialized data .bss -- the location and alignment of the memory section to store uninitialized data .heap -- the location and alignment of the memory section to provide system memory The linker script should specify the location and size of the different memory regions in your BSP and map the code sections described above into these regions. The linker script should also include an ENTRY point. This is used by the debugger to know where to start the program counter when the target is debugged. There may be additional requirements from the MCU or OS that you may find easiest to place in the linker script. Some specific variables that the OS and MCU depends on are : Variable Description __bss_start__ a variable located at the start of the BSS section __bss_end__ a variable located at the end of the BSS section __isr_vector Some CPUs map their interrupt vectors. They may need to be specified in the linker _user_heap_start the start of the heap for unallocated memory _user_heap_end the end of the heap for unallocated memory Create an alternate linker script for the bootloader since it is typically linked to use different addresses to boot the main image. Add Functions and Defines At this point, it will be possible to run the newt tool to build your target. You may run into complaints from the linker script that a few Mynewt specific functions are missing. We will describe these below. Function Description os_bsp_init() code to initialize the bsp os_bsp_systick_init() code to setup the system tick for the OS There are also several libc definitions that can be stubbed in your first BSP. Examples are _write , _read , etc. that can be found in libc_stubs.c . But you must implement the following function to provide memory to the OS and system. Function Description _sbrk Returns memory from heap (used by malloc) Implement _sbrk() sbrk() is required by libc to get memory from the heap for things like malloc. Although not strongly BSP dependent, this is currently in the BSP to allow flexibility in providing system memory. See other BSPs for providing sbrk functionality. Implement os_bsp_init() os_bsp_init should initialize anything required in the OS by the BSP. Typically this is a very small set. NOTE : Currently we are making calls to _sbrk() and close(0) from os_bsp_init to get around a linker issue where some of libc is not getting included. Please include this in your os_bsp_init . /* * XXX these references are here to keep the functions in for libc to find. */ _sbrk ( 0 ); _close ( 0 ); Other Unresolved Defines or Functions There may be other unresolved defines or functions that are required by the specific MCU within your BSP. Below lists some sample defines. Undefined Variable Description CONSOLE_UART_PORT Which communications port on your target runs the console LED_BLINK_PIN which pin on your target runs the blinky LED The set of missing functionality depends upon the libraries and dependencies you have included in the project. That's why its best to keep your first project pretty simple then add incrementally. For example, if you include the Newtron file system, you will need to define a file system map for your BSP. Missing functionality may take the form of #define items required to compile, or they may take the form of missing functions. cmsis_nvic.h If you are using an ARM cortex architecture, you need to define the number of interrupts supported by your system. If you are not using ARM Cortex architecture this may not be required (but something else might be). Add Debug Script The debug script in the bsp directory allows the newt tool to automatically connect to the debugger and create a debug session with the target. This requires knowledge of your target debug interface. Most of the Mynewt BSP targets use openocd to perform debugging. This script typically creates an openocd connection to the target and then connects a gdb instance to this openocd connection. There are several examples in existing BSPs to follow. The script must take a single argument which is the name of the image file minus the '.elf' suffix. The BSP is complete without this file, but newt will be unable to establish a debug session without it. Add Download Script Similar to the debug script, the download script is a hook for newt to download the image to the target system. The download script also typically uses the openocd interface to erase flash and progam the code into the device. NOTE: The download script needs to command openocd to program the image into the appropriate location which is typically called FLASH_OFFSET in these scripts. This location has to match the linker script location of the image link address. For example, if your linker links the code to be run at 0xC000 your download script should download the image to the same address in the correct flash. Add License and Documentation The LICENSE file is an ASCII text file that describes the source license for this package. The README.md is a markdown file that contains any documentation you want to provide for the BSP.","title":"BSP Porting"},{"location":"os/core_os/porting/port_bsp/#create-a-bsp-for-your-target","text":"","title":"Create a BSP for your Target"},{"location":"os/core_os/porting/port_bsp/#introduction","text":"If you are using a board or system not currently supported by Mynewt, you will need to create a BSP for the new target. If another similar BSP exists it is recommended to copy that BSP as a starting point. For example, if another BSP exists using the same MCU, start with a copy of that BSP. Either way, this document describes the steps necessary to create a new BSP from scratch.","title":"Introduction"},{"location":"os/core_os/porting/port_bsp/#keep-your-reference-documents-handy","text":"To build a proper BSP, you will typically need the following: The datasheet for the MCU you have chosen The schematic of your board The information on the CPU core within your MCU if it is not included in your MCU documentation This Mynewt documentation","title":"Keep your Reference Documents handy"},{"location":"os/core_os/porting/port_bsp/#name-your-bsp","text":"Select a name for your BSP. For the remainder of this document, we'll assume the bsp is named myboard . In general its best to select a name that describes the board/system you are creating.","title":"Name your BSP"},{"location":"os/core_os/porting/port_bsp/#create-a-bsp-directory","text":"Create a directory hw/bsp/myboard using the name chosen above. Within this BSP directory, create the following subdirectories: include include/bsp src","title":"Create a BSP directory"},{"location":"os/core_os/porting/port_bsp/#create-a-target-using-mynewt","text":"Create a newt target for your test project for the BSP. To learn how to create a target, see this howto Tutorial . Once you are familiar with creating targets, move on below to create a target to use to test your BSP. It is recommended that you use a simple project like blinky to minimize the time to get a working Mynewt system. For this document, we will assume the target is called myboard_blinky and uses project blinky . Set the bsp of the project to /hw/bsp/myboard . While creating your target, you will need to specify your arch and compiler . If your platform requires an architecture or compiler that are not defined in Mynewt, you will need to add them first. To add a CPU architecture see CPU Porting . When this is complete, your target may look similar to this. $ newt target show myboard_blinky arch=cortex_m0 bsp=hw/bsp/myboard compiler=arm-none-eabi-m0 compiler_def=debug name=myboard_blinky project=blinky","title":"Create a Target using Mynewt"},{"location":"os/core_os/porting/port_bsp/#create-required-files-for-compilation","text":"Create the following files within the BSP directory tree. For now, they can be empty files. We will fill them out one at a time. File Path Name Description LICENSE A File to present the source license for your BSP README.md A markdown file to write documentation for your BSP pkg.yml A package file to describe your BSP contents include/bsp/bsp.h A header file to include definitions required by system from the BSP include/bsp/bsp_sysid.h A header file to enumerate the devices in your BSP src/os_bsp.c A C source file to provide functions required by the OS from your BSP src/sbrk.c A C source file to memory from your heap to the OS src/libc_stubs.c A C source file to provide stubs/methods required by libc myboard.ld A linker script to provide the memory map for your linked code Optionally, create these files as necessary to provide all functionality from Mynewt. File Path Name Description myboard_boot.ld A linker script to provide the memory map for your bootloader myboard_download.sh A bash script to download code into your platform myboard_debug.sh A bash script to intiate a gdb session with your platform src/hal_bsp.c A C source file to provide functions required by the HAL from your BSP","title":"Create Required Files For Compilation"},{"location":"os/core_os/porting/port_bsp/#fill-out-your-package-file","text":"Edit the package file to describe your BSP. The package file must contain: pkg.name: \"hw/bsp/myboard\" pkg.linkerscript: \"myboard.ld\" Attribute Description pkg.name The name of your bsp package pkg.linkerscript The linker script that controls the memory placement of the compiled code sections from the Mynewt OS and your applications. The linker script is a key component of the BSP and specifies where each section of code and data are stored within your CPU which can vary with the BSP depending on your chosen memory layout. For a tutorial on writing linker scripts, see Create or Copy Linker Script(s) . The package file typically contains: pkg.linkerscript.bootloader.OVERWRITE: \"myboard_boot.ld\" pkg.downloadscript: \"myboard_download.sh\" pkg.debugscript: \"myboard_debug.sh\" pkg.deps: - hw/mcu/mymcu/variant where mymcu/variant should be replaced with the specific MCU and variant used in your design. The following table describes additional attributes relevant to the BSP pkg.yml file. Attribute Description pkg.linkerscript.bootloader.OVERWRITE A special linker for creating a bootloader for Mynewt pkg.downloadscript A script that can download a flash image into your target platform pkg.debugscript A script that can run the GDB debugger on your board pkg.deps Any dependencies on your BSP The BSP will invariably depend upon an MCU (in this sample it's hw/mcu/mymcu/variant ) since the Mynewt OS runs on an MCU within your target. If your MCU is not supported by Mynewt, see MCU Porting for details on how to create a new MCU in Mynewt. The package file may also contain: pkg.cflags: -D__MY_SPECIAL_BSP_OPTIONS_ pkg.deps: - libs/cmsis-core Attribute Description pkg.cflags Any specific compiler flags for your bsp pkg.deps Any other libraries that may be required. Some architectures (like ARM) have special libraries to make BSP creation easier.","title":"Fill Out your Package File"},{"location":"os/core_os/porting/port_bsp/#create-or-copy-linker-script","text":"It's probably best to start with a linker script from another BSP using the same MCU. If this is not available, consult your MCU documentation and library samples to find a linker script to start with. Typically, a linker script has to specify the following sections for code: .text -- the location and alignment of the memory section to store your code .data -- the location and alignment of the memory section to store initialized data .bss -- the location and alignment of the memory section to store uninitialized data .heap -- the location and alignment of the memory section to provide system memory The linker script should specify the location and size of the different memory regions in your BSP and map the code sections described above into these regions. The linker script should also include an ENTRY point. This is used by the debugger to know where to start the program counter when the target is debugged. There may be additional requirements from the MCU or OS that you may find easiest to place in the linker script. Some specific variables that the OS and MCU depends on are : Variable Description __bss_start__ a variable located at the start of the BSS section __bss_end__ a variable located at the end of the BSS section __isr_vector Some CPUs map their interrupt vectors. They may need to be specified in the linker _user_heap_start the start of the heap for unallocated memory _user_heap_end the end of the heap for unallocated memory Create an alternate linker script for the bootloader since it is typically linked to use different addresses to boot the main image.","title":"Create or Copy Linker Script"},{"location":"os/core_os/porting/port_bsp/#add-functions-and-defines","text":"At this point, it will be possible to run the newt tool to build your target. You may run into complaints from the linker script that a few Mynewt specific functions are missing. We will describe these below. Function Description os_bsp_init() code to initialize the bsp os_bsp_systick_init() code to setup the system tick for the OS There are also several libc definitions that can be stubbed in your first BSP. Examples are _write , _read , etc. that can be found in libc_stubs.c . But you must implement the following function to provide memory to the OS and system. Function Description _sbrk Returns memory from heap (used by malloc) Implement _sbrk() sbrk() is required by libc to get memory from the heap for things like malloc. Although not strongly BSP dependent, this is currently in the BSP to allow flexibility in providing system memory. See other BSPs for providing sbrk functionality. Implement os_bsp_init() os_bsp_init should initialize anything required in the OS by the BSP. Typically this is a very small set. NOTE : Currently we are making calls to _sbrk() and close(0) from os_bsp_init to get around a linker issue where some of libc is not getting included. Please include this in your os_bsp_init . /* * XXX these references are here to keep the functions in for libc to find. */ _sbrk ( 0 ); _close ( 0 ); Other Unresolved Defines or Functions There may be other unresolved defines or functions that are required by the specific MCU within your BSP. Below lists some sample defines. Undefined Variable Description CONSOLE_UART_PORT Which communications port on your target runs the console LED_BLINK_PIN which pin on your target runs the blinky LED The set of missing functionality depends upon the libraries and dependencies you have included in the project. That's why its best to keep your first project pretty simple then add incrementally. For example, if you include the Newtron file system, you will need to define a file system map for your BSP. Missing functionality may take the form of #define items required to compile, or they may take the form of missing functions. cmsis_nvic.h If you are using an ARM cortex architecture, you need to define the number of interrupts supported by your system. If you are not using ARM Cortex architecture this may not be required (but something else might be).","title":"Add Functions and Defines"},{"location":"os/core_os/porting/port_bsp/#add-debug-script","text":"The debug script in the bsp directory allows the newt tool to automatically connect to the debugger and create a debug session with the target. This requires knowledge of your target debug interface. Most of the Mynewt BSP targets use openocd to perform debugging. This script typically creates an openocd connection to the target and then connects a gdb instance to this openocd connection. There are several examples in existing BSPs to follow. The script must take a single argument which is the name of the image file minus the '.elf' suffix. The BSP is complete without this file, but newt will be unable to establish a debug session without it.","title":"Add Debug Script"},{"location":"os/core_os/porting/port_bsp/#add-download-script","text":"Similar to the debug script, the download script is a hook for newt to download the image to the target system. The download script also typically uses the openocd interface to erase flash and progam the code into the device. NOTE: The download script needs to command openocd to program the image into the appropriate location which is typically called FLASH_OFFSET in these scripts. This location has to match the linker script location of the image link address. For example, if your linker links the code to be run at 0xC000 your download script should download the image to the same address in the correct flash.","title":"Add Download Script"},{"location":"os/core_os/porting/port_bsp/#add-license-and-documentation","text":"The LICENSE file is an ASCII text file that describes the source license for this package. The README.md is a markdown file that contains any documentation you want to provide for the BSP.","title":"Add License and Documentation"},{"location":"os/core_os/porting/port_cpu/","text":"Porting Mynewt to a new CPU Architecture A new CPU architecture typically requires the following: A new compiler New architecture-specific code for the OS Helper libraries to help others porting to the same architecture These are discussed below: Create A New Compiler NOTE: Newt does not automatically install the compilers require to build all platforms. It's up to the user using their local machines package manager to install the compilers. The steps described here just registers the compiler with newt. Create a new directory (named after the compiler you are adding). Copy the pkg.yml file from another compiler. Edit the pkg.yml file and change the configuration attributes to match your compiler. Most are self-explanatory paths to different compiler and linker tools. There are a few configuration attributes worth noting. Configuration Attributes Description pkg.keywords Specific keywords to help others search for this using newt compiler.flags.default default compiler flags for this architecture compiler.flags.optimized additional flags when the newt tool builds an optimized image compiler.flags.debug additional flags when the newt tool builds a debug image Implement Architecture-specific OS code There are several architecture-specific code functions that are required when implementing a new architecture. You can find examples in the sim architecture within Mynewt. When porting to a new CPU architecture, use the existing architectures as samples when writing your implementation. Please contact the Mynewt development list for help and advice portingto new MCU.","title":"CPU Porting"},{"location":"os/core_os/porting/port_cpu/#porting-mynewt-to-a-new-cpu-architecture","text":"A new CPU architecture typically requires the following: A new compiler New architecture-specific code for the OS Helper libraries to help others porting to the same architecture These are discussed below:","title":"Porting Mynewt to a new CPU Architecture"},{"location":"os/core_os/porting/port_cpu/#create-a-new-compiler","text":"NOTE: Newt does not automatically install the compilers require to build all platforms. It's up to the user using their local machines package manager to install the compilers. The steps described here just registers the compiler with newt. Create a new directory (named after the compiler you are adding). Copy the pkg.yml file from another compiler. Edit the pkg.yml file and change the configuration attributes to match your compiler. Most are self-explanatory paths to different compiler and linker tools. There are a few configuration attributes worth noting. Configuration Attributes Description pkg.keywords Specific keywords to help others search for this using newt compiler.flags.default default compiler flags for this architecture compiler.flags.optimized additional flags when the newt tool builds an optimized image compiler.flags.debug additional flags when the newt tool builds a debug image","title":"Create A New Compiler"},{"location":"os/core_os/porting/port_cpu/#implement-architecture-specific-os-code","text":"There are several architecture-specific code functions that are required when implementing a new architecture. You can find examples in the sim architecture within Mynewt. When porting to a new CPU architecture, use the existing architectures as samples when writing your implementation. Please contact the Mynewt development list for help and advice portingto new MCU.","title":"Implement Architecture-specific OS code"},{"location":"os/core_os/porting/port_mcu/","text":"Porting Mynewt to a new MCU Porting Mynewt to a new MCU is not a difficult task if the core CPU architectures is already supported. The depth of work depends on the amount of HAL (Hardware Abstraction Layer) support you need and provide in your port. To get started: Create a hw/mcu/mymcu directory where mymcu is the MCU you are porting to. Replace the name mymcu with a description of the MCU you are using. Create a hw/mcu/mymcu/variant directory where the variant is the specific variant of the part you are usuing. Many MCU parts have variants with different capabilities (RAM, FLASH etc) or different pinouts. Replace variant with a description of the variant of the part you are using. Create a hw/mcu/mymcu/variant/pkg.yml file. Copy from another mcu and fill out the relevant information Create hw/mcu/mymcu/variant/include , hw/mcu/mymcu/variant/include/mcu , and hw/mcu/mymcu/variant/src directories to contain the code for your mcu. At this point there are two main tasks to complete. Implement any OS-specific code required by the OS Implement the HAL functionality that you are looking for Please contact the Mynewt development list for help and advice porting to new MCU.","title":"MCU Porting"},{"location":"os/core_os/porting/port_mcu/#porting-mynewt-to-a-new-mcu","text":"Porting Mynewt to a new MCU is not a difficult task if the core CPU architectures is already supported. The depth of work depends on the amount of HAL (Hardware Abstraction Layer) support you need and provide in your port. To get started: Create a hw/mcu/mymcu directory where mymcu is the MCU you are porting to. Replace the name mymcu with a description of the MCU you are using. Create a hw/mcu/mymcu/variant directory where the variant is the specific variant of the part you are usuing. Many MCU parts have variants with different capabilities (RAM, FLASH etc) or different pinouts. Replace variant with a description of the variant of the part you are using. Create a hw/mcu/mymcu/variant/pkg.yml file. Copy from another mcu and fill out the relevant information Create hw/mcu/mymcu/variant/include , hw/mcu/mymcu/variant/include/mcu , and hw/mcu/mymcu/variant/src directories to contain the code for your mcu. At this point there are two main tasks to complete. Implement any OS-specific code required by the OS Implement the HAL functionality that you are looking for Please contact the Mynewt development list for help and advice porting to new MCU.","title":"Porting Mynewt to a new MCU"},{"location":"os/core_os/porting/port_os/","text":"Porting Mynewt OS This chapter describes how to adapt the Mynewt OS to different platforms. Description The Mynewt OS is a complete multi-tasking environment with scheduler, time control, buffer management, and synchronization objects. it also includes libraries and services like console, command shell, image manager, bootloader, and file systems etc. Thee majority of this software is platform independent and requires no intervention to run on your platform, but some of the components require support from the underlying platform. The platform dependency of these components can fall into several categories: CPU Core Dependencies -- Specific code or configuration to operate the CPU core within your target platform MCU Dependencies -- Specific code or configuration to operate the MCU or SoC within your target platform BSP Dependencies -- Specific code or configuration to accommodate the specific layout and functionality of your target platform Board Support Package (BSP) Dependency With all of the functionality provided by the core, MCU, and MCU HAL (Hardware Abstraction Layer), there are still some things that must be specified for your particular system. This is provided in Mynewt to allow you the flexibility to design for the exact functionality, peripherals and features that you require in your product. In Mynewt, these settings/components are included in a Board Support Package (BSP). The BSP contains the information specific to running Mynewt on a target platform or hardware board. Mynewt supports some common open source hardware as well as the development boards for some common MCUs. These development systems might be enough for you to get your prototype up and running, but when building a product you are likely going to have your own board which is slightly different from those already supported by Mynewt. For example, you might decide on your system that 16 Kilobytes of flash space in one flash device is reserved for a flash file system. Or on your system you may decide that GPIO pin 5 of the MCU is connected to the system LED. Or you may decide that the OS Tick (the underlying time source for the OS) should run slower than the defaults to conserve battery power. These types of behaviors are specified in the BSP. The information provided in the BSP (what you need to specify to get a complete executable) can vary depending on the MCU and its underlying core architecture. For example, some MCUs have dedicated pins for UART, SPI etc, so there is no configuration required in the BSP when using these peripherals. However some MCUs have a pin multiplexor that allows the UART to be mapped to several different pins. For these MCUs, the BSP must specify if and where the UART pins should appear to match the hardware layout of your system. If your BSP is already supported my Mynewt, there is no additional BSP work involved in porting to your platform. You need only set the bsp attribute in your Mynewt target using the newt command tool . If your BSP is not yet supported by Mynewt, you can add support by following the instructions on how to add BSP support to Mynewt MCU Dependency Some OS code depends on the MCU or SoC that the system contains. For example, the MCU may specify the potential memory map of the system - where code and data can reside. If your MCU is already supported by Mynewt, there is no additional MCU work involved in porting to your platform. You need only set the arch attribute in your Mynewt target using the newt command tool . If your MCU is not yet supported by Mynewt, you can add support by following the instructions on how to add MCU support to Mynewt MCU Hardware Abstraction Layer (HAL) Mynewt's architecture supports a hardware abstraction layer (HAL) for common on or off-chip MCU peripherals such as GPIO, UARTs, flash memory etc. Even if your MCU is supported for the core OS, you may find that you need to implement the HAL functionality for a new peripheral. For a description of the HAL abstraction and implementation information, see the HAL API CPU Core Dependency Some OS code depends on the CPU core that your system is using. For example, a given CPU core has a specific assembly language instruction set, and may require special cross compiler or compiler settings to use the appropriate instruction set. If your CPU architecture is already supported by Mynewt, there is no CPU core work involved in porting to your platform. You need only set the arch and compiler attributes in your Mynewt target using the newt command tool . If your CPU architecture is not supported by Mynewt, you can add support by following the instructions on how to add CPU architecture support to Mynewt","title":"toc"},{"location":"os/core_os/porting/port_os/#porting-mynewt-os","text":"This chapter describes how to adapt the Mynewt OS to different platforms.","title":"Porting Mynewt OS"},{"location":"os/core_os/porting/port_os/#description","text":"The Mynewt OS is a complete multi-tasking environment with scheduler, time control, buffer management, and synchronization objects. it also includes libraries and services like console, command shell, image manager, bootloader, and file systems etc. Thee majority of this software is platform independent and requires no intervention to run on your platform, but some of the components require support from the underlying platform. The platform dependency of these components can fall into several categories: CPU Core Dependencies -- Specific code or configuration to operate the CPU core within your target platform MCU Dependencies -- Specific code or configuration to operate the MCU or SoC within your target platform BSP Dependencies -- Specific code or configuration to accommodate the specific layout and functionality of your target platform","title":"Description"},{"location":"os/core_os/porting/port_os/#board-support-package-bsp-dependency","text":"With all of the functionality provided by the core, MCU, and MCU HAL (Hardware Abstraction Layer), there are still some things that must be specified for your particular system. This is provided in Mynewt to allow you the flexibility to design for the exact functionality, peripherals and features that you require in your product. In Mynewt, these settings/components are included in a Board Support Package (BSP). The BSP contains the information specific to running Mynewt on a target platform or hardware board. Mynewt supports some common open source hardware as well as the development boards for some common MCUs. These development systems might be enough for you to get your prototype up and running, but when building a product you are likely going to have your own board which is slightly different from those already supported by Mynewt. For example, you might decide on your system that 16 Kilobytes of flash space in one flash device is reserved for a flash file system. Or on your system you may decide that GPIO pin 5 of the MCU is connected to the system LED. Or you may decide that the OS Tick (the underlying time source for the OS) should run slower than the defaults to conserve battery power. These types of behaviors are specified in the BSP. The information provided in the BSP (what you need to specify to get a complete executable) can vary depending on the MCU and its underlying core architecture. For example, some MCUs have dedicated pins for UART, SPI etc, so there is no configuration required in the BSP when using these peripherals. However some MCUs have a pin multiplexor that allows the UART to be mapped to several different pins. For these MCUs, the BSP must specify if and where the UART pins should appear to match the hardware layout of your system. If your BSP is already supported my Mynewt, there is no additional BSP work involved in porting to your platform. You need only set the bsp attribute in your Mynewt target using the newt command tool . If your BSP is not yet supported by Mynewt, you can add support by following the instructions on how to add BSP support to Mynewt","title":"Board Support Package (BSP) Dependency"},{"location":"os/core_os/porting/port_os/#mcu-dependency","text":"Some OS code depends on the MCU or SoC that the system contains. For example, the MCU may specify the potential memory map of the system - where code and data can reside. If your MCU is already supported by Mynewt, there is no additional MCU work involved in porting to your platform. You need only set the arch attribute in your Mynewt target using the newt command tool . If your MCU is not yet supported by Mynewt, you can add support by following the instructions on how to add MCU support to Mynewt","title":"MCU Dependency"},{"location":"os/core_os/porting/port_os/#mcu-hardware-abstraction-layer-hal","text":"Mynewt's architecture supports a hardware abstraction layer (HAL) for common on or off-chip MCU peripherals such as GPIO, UARTs, flash memory etc. Even if your MCU is supported for the core OS, you may find that you need to implement the HAL functionality for a new peripheral. For a description of the HAL abstraction and implementation information, see the HAL API","title":"MCU Hardware Abstraction Layer (HAL)"},{"location":"os/core_os/porting/port_os/#cpu-core-dependency","text":"Some OS code depends on the CPU core that your system is using. For example, a given CPU core has a specific assembly language instruction set, and may require special cross compiler or compiler settings to use the appropriate instruction set. If your CPU architecture is already supported by Mynewt, there is no CPU core work involved in porting to your platform. You need only set the arch and compiler attributes in your Mynewt target using the newt command tool . If your CPU architecture is not supported by Mynewt, you can add support by following the instructions on how to add CPU architecture support to Mynewt","title":"CPU Core Dependency"},{"location":"os/core_os/sanity/os_sanity_check_init/","text":"os_sanity_check_init int os_sanity_check_init ( struct os_sanity_check *sc ) Initialize the sanity check pointed to by sc . Sets default values, and ensures memory is cleared out. Arguments Arguments Description sc Pointer to sanity check Returned values OS_OK : sanity check initialization is successful All other error codes indicate an error. Example int rc ; rc = os_sanity_task_check_init ( &my_sanity_check ); assert ( rc == OS_OK );","title":"os_sanity_check_init"},{"location":"os/core_os/sanity/os_sanity_check_init/#os_sanity_check_init","text":"int os_sanity_check_init ( struct os_sanity_check *sc ) Initialize the sanity check pointed to by sc . Sets default values, and ensures memory is cleared out.","title":" os_sanity_check_init"},{"location":"os/core_os/sanity/os_sanity_check_init/#arguments","text":"Arguments Description sc Pointer to sanity check","title":"Arguments"},{"location":"os/core_os/sanity/os_sanity_check_init/#returned-values","text":"OS_OK : sanity check initialization is successful All other error codes indicate an error.","title":"Returned values"},{"location":"os/core_os/sanity/os_sanity_check_init/#example","text":"int rc ; rc = os_sanity_task_check_init ( &my_sanity_check ); assert ( rc == OS_OK );","title":"Example"},{"location":"os/core_os/sanity/os_sanity_check_register/","text":"os_sanity_check_register int os_sanity_check_register ( struct os_sanity_check *sc ) Register the sanity check pointed to by sc with the sanity task. After registration the sanity task will check this sanity check with every run of the sanity task. Arguments Arguments Description sc Pointer to sanity check Returned values OS_OK : sanity check successfully registered All other error codes indicate an error. Example int rc ; rc = os_sanity_check_register ( &my_sc ); assert ( rc == OS_OK );","title":"os_sanity_check_register"},{"location":"os/core_os/sanity/os_sanity_check_register/#os_sanity_check_register","text":"int os_sanity_check_register ( struct os_sanity_check *sc ) Register the sanity check pointed to by sc with the sanity task. After registration the sanity task will check this sanity check with every run of the sanity task.","title":" os_sanity_check_register"},{"location":"os/core_os/sanity/os_sanity_check_register/#arguments","text":"Arguments Description sc Pointer to sanity check","title":"Arguments"},{"location":"os/core_os/sanity/os_sanity_check_register/#returned-values","text":"OS_OK : sanity check successfully registered All other error codes indicate an error.","title":"Returned values"},{"location":"os/core_os/sanity/os_sanity_check_register/#example","text":"int rc ; rc = os_sanity_check_register ( &my_sc ); assert ( rc == OS_OK );","title":"Example"},{"location":"os/core_os/sanity/os_sanity_check_reset/","text":"os_sanity_check_reset int os_sanity_check_reset ( struct os_sanity_check *sc ) Reset the sanity check pointed to by sc. This tells the sanity task that this sanity check is considered valid for another sc_checkin_itvl time ticks. Arguments Arguments Description sc Pointer to sanity check Returned values OS_OK : sanity check reset successful All other error codes indicate an error. Example int rc ; rc = os_sanity_check_reset ( &my_sc ); assert ( rc == OS_OK );","title":"os_sanity_check_reset"},{"location":"os/core_os/sanity/os_sanity_check_reset/#os_sanity_check_reset","text":"int os_sanity_check_reset ( struct os_sanity_check *sc ) Reset the sanity check pointed to by sc. This tells the sanity task that this sanity check is considered valid for another sc_checkin_itvl time ticks.","title":" os_sanity_check_reset"},{"location":"os/core_os/sanity/os_sanity_check_reset/#arguments","text":"Arguments Description sc Pointer to sanity check","title":"Arguments"},{"location":"os/core_os/sanity/os_sanity_check_reset/#returned-values","text":"OS_OK : sanity check reset successful All other error codes indicate an error.","title":"Returned values"},{"location":"os/core_os/sanity/os_sanity_check_reset/#example","text":"int rc ; rc = os_sanity_check_reset ( &my_sc ); assert ( rc == OS_OK );","title":"Example"},{"location":"os/core_os/sanity/os_sanity_task_checkin/","text":"os_sanity_task_checkin int os_sanity_task_checkin ( struct os_task *t ) Used by a task to check in to the sanity task. This informs the sanity task that task is still alive and working normally. Arguments Arguments Description t Pointer to task Returned values OS_OK : sanity check-in successful All other error codes indicate an error. Example int rc ; rc = os_sanity_task_checkin ( &my_task ); assert ( rc == OS_OK );","title":"os_sanity_task_checkin"},{"location":"os/core_os/sanity/os_sanity_task_checkin/#os_sanity_task_checkin","text":"int os_sanity_task_checkin ( struct os_task *t ) Used by a task to check in to the sanity task. This informs the sanity task that task is still alive and working normally.","title":" os_sanity_task_checkin"},{"location":"os/core_os/sanity/os_sanity_task_checkin/#arguments","text":"Arguments Description t Pointer to task","title":"Arguments"},{"location":"os/core_os/sanity/os_sanity_task_checkin/#returned-values","text":"OS_OK : sanity check-in successful All other error codes indicate an error.","title":"Returned values"},{"location":"os/core_os/sanity/os_sanity_task_checkin/#example","text":"int rc ; rc = os_sanity_task_checkin ( &my_task ); assert ( rc == OS_OK );","title":"Example"},{"location":"os/core_os/sanity/os_sanity_task_init/","text":"os_sanity_task_init int os_sanity_task_init ( int num_secs ); Initialize the os sanity task. num_secs is the number of seconds to wait in between runs of the sanity task. Arguments Arguments Description num_secs Number of seconds to wait in between running sanity checks. Returned values OS_OK : Sanity task was successfully created. All other error codes indicate an error. Example /* Run sanity checks every 50 seconds */ #define SANITY_TASK_INTERVAL (50) int rc ; rc = os_sanity_task_init ( SANITY_TASK_INTERVAL ); assert ( rc == OS_OK );","title":"os_sanity_task_init"},{"location":"os/core_os/sanity/os_sanity_task_init/#os_sanity_task_init","text":"int os_sanity_task_init ( int num_secs ); Initialize the os sanity task. num_secs is the number of seconds to wait in between runs of the sanity task.","title":" os_sanity_task_init"},{"location":"os/core_os/sanity/os_sanity_task_init/#arguments","text":"Arguments Description num_secs Number of seconds to wait in between running sanity checks.","title":"Arguments"},{"location":"os/core_os/sanity/os_sanity_task_init/#returned-values","text":"OS_OK : Sanity task was successfully created. All other error codes indicate an error.","title":"Returned values"},{"location":"os/core_os/sanity/os_sanity_task_init/#example","text":"/* Run sanity checks every 50 seconds */ #define SANITY_TASK_INTERVAL (50) int rc ; rc = os_sanity_task_init ( SANITY_TASK_INTERVAL ); assert ( rc == OS_OK );","title":"Example"},{"location":"os/core_os/sanity/sanity/","text":"Sanity The Sanity task is a software watchdog task, which runs periodically to check system state, and ensure that everything is still operating properly. In a typical system design, there are multiple stages of watchdog: Internal Watchdog External Watchdog Sanity Watchdog The Internal Watchdog is typically an MCU watchdog, which is tickled in the core of the OS. The internal watchdog is tickled frequently, and is meant to be an indicator the OS is running. The External Watchdog is a watchdog that's typically run slower. The purpose of an external watchdog is to provide the system with a hard reset when it has lost its mind. The Sanity Watchdog is the least frequently run watchdog, and is meant as an application watchdog. This document is about the operation of the Mynewt Sanity Watchdog. Description Initializing the Sanity Task The Sanity Watchdog is a task in the Mynewt OS, which when enabled, runs every sanity_seconds . In order to enable the Sanity Watchdog task, call the os_sanity_task_init() function. int os_sanity_task_init ( int sanity_seconds ); By default, every operating system task provides the frequency it will check in with the sanity task, with the sanity_itvl parameter in the os_task_init() function: int os_task_init ( struct os_task *t , char *name , os_task_func_t func , void *arg , uint8_t prio , os_time_t sanity_itvl , os_stack_t *bottom , uint16_t stack_size ); sanity_itvl is the time in OS time ticks that the task being created must register in with the sanity task. Checking in with Sanity Task The task must then register in with the sanity task every sanity_itvl seconds. In order to do that, the task should call the os_sanity_task_checkin function, which will reset the sanity check associated with this task. Here is an example of a task that uses a callout to checkin with the sanity task every 50 seconds: #define TASK1_SANITY_CHECKIN_ITVL (50 * OS_TICKS_PER_SEC) struct os_eventq task1_evq ; static void task1 ( void *arg ) { struct os_task *t ; struct os_event *ev ; struct os_callout c ; /* Get current OS task */ t = os_sched_get_current_task (); /* Initialize the event queue. */ os_eventq_init ( &task1_evq ); /* Initialize the callout */ os_callout_init ( &c , &task1_evq , NULL ); /* reset the callout to checkin with the sanity task * in 50 seconds to kick off timing. */ os_callout_reset ( &c , TASK1_SANITY_CHECKIN_ITVL ); while ( 1 ) { ev = os_eventq_get ( &task1_evq ); /* The sanity timer has reset */ if ( ev->ev_arg == &c ) { os_sanity_task_checkin ( t ); } else { /* not expecting any other events */ assert ( 0 ); } } /* Should never reach */ assert ( 0 ); } Registering a Custom Sanity Check If a particular task wants to further hook into the sanity framework to perform other checks during the sanity task's operation, it can do so by registering a struct os_sanity_check using the os_sanity_check_register function. static int mymodule_perform_sanity_check ( struct os_sanity_check *sc , void *arg ) { /* Perform your checking here. In this case, we check if there * are available buffers in mymodule, and return 0 (all good) * if true, and -1 (error) if not. */ if ( mymodule_has_buffers ()) { return ( 0 ); } else { return ( -1 ); } } static int mymodule_register_sanity_check ( void ) { struct os_sanity_check sc ; os_sanity_check_init ( &sc ); /* Only assert() if mymodule_perform_sanity_check() fails 50 * times. SANITY_TASK_INTERVAL is defined by the user, and * is the frequency at which the sanity_task runs in seconds. */ OS_SANITY_CHECK_SETFUNC ( &sc , mymodule_perform_sanity_check , NULL , 50 * SANITY_TASK_INTERVAL ); rc = os_sanity_check_register ( &sc ); if ( rc != 0 ) { goto err ; } return ( 0 ); err : return ( rc ); } In the above example, every time the custom sanity check mymodule_perform_sanity_check returns successfully (0), the sanity check is reset. In the OS_SANITY_CHECK_SETFUNC macro, the sanity checkin interval is specified as 50 * SANITY_TASK_INTERVAL (which is the interval at which the sanity task runs.) This means that the mymodule_perform_sanity_check() function needs to fail 50 times consecutively before the sanity task will crash the system. TIP: When checking things like memory buffers, which can be temporarily be exhausted, it's a good idea to have the sanity check fail multiple consecutive times before crashing the system. This will avoid crashing for temporary failures. Data structures OS Sanity Check struct os_sanity_check { os_time_t sc_checkin_last ; os_time_t sc_checkin_itvl ; os_sanity_check_func_t sc_func ; void *sc_arg ; SLIST_ENTRY ( os_sanity_check ) sc_next ; }; Element Description sc_checkin_last The last time this sanity check checked in with the sanity task, in OS time ticks. sc_checkin_itvl How frequently the sanity check is supposed to check in with the sanity task, in OS time ticks. sc_func If not NULL , call this function when running the sanity task. If the function returns 0, reset the sanity check. sc_arg Argument to pass to sc_func when calling it. sc_next Sanity checks are chained in the sanity task when os_sanity_check_register() is called. List of Functions The functions available in sanity are: Function Description os_sanity_check_init Initialize the given sanity check. os_sanity_check_register Register the given sanity check with the sanity task. os_sanity_check_reset Reset the given sanity check. os_sanity_task_checkin Informs the sanity task that the given task is still alive and working normally. os_sanity_task_init Initialize the os sanity task.","title":"toc"},{"location":"os/core_os/sanity/sanity/#sanity","text":"The Sanity task is a software watchdog task, which runs periodically to check system state, and ensure that everything is still operating properly. In a typical system design, there are multiple stages of watchdog: Internal Watchdog External Watchdog Sanity Watchdog The Internal Watchdog is typically an MCU watchdog, which is tickled in the core of the OS. The internal watchdog is tickled frequently, and is meant to be an indicator the OS is running. The External Watchdog is a watchdog that's typically run slower. The purpose of an external watchdog is to provide the system with a hard reset when it has lost its mind. The Sanity Watchdog is the least frequently run watchdog, and is meant as an application watchdog. This document is about the operation of the Mynewt Sanity Watchdog.","title":"Sanity"},{"location":"os/core_os/sanity/sanity/#description","text":"","title":"Description"},{"location":"os/core_os/sanity/sanity/#initializing-the-sanity-task","text":"The Sanity Watchdog is a task in the Mynewt OS, which when enabled, runs every sanity_seconds . In order to enable the Sanity Watchdog task, call the os_sanity_task_init() function. int os_sanity_task_init ( int sanity_seconds ); By default, every operating system task provides the frequency it will check in with the sanity task, with the sanity_itvl parameter in the os_task_init() function: int os_task_init ( struct os_task *t , char *name , os_task_func_t func , void *arg , uint8_t prio , os_time_t sanity_itvl , os_stack_t *bottom , uint16_t stack_size ); sanity_itvl is the time in OS time ticks that the task being created must register in with the sanity task.","title":"Initializing the Sanity Task"},{"location":"os/core_os/sanity/sanity/#checking-in-with-sanity-task","text":"The task must then register in with the sanity task every sanity_itvl seconds. In order to do that, the task should call the os_sanity_task_checkin function, which will reset the sanity check associated with this task. Here is an example of a task that uses a callout to checkin with the sanity task every 50 seconds: #define TASK1_SANITY_CHECKIN_ITVL (50 * OS_TICKS_PER_SEC) struct os_eventq task1_evq ; static void task1 ( void *arg ) { struct os_task *t ; struct os_event *ev ; struct os_callout c ; /* Get current OS task */ t = os_sched_get_current_task (); /* Initialize the event queue. */ os_eventq_init ( &task1_evq ); /* Initialize the callout */ os_callout_init ( &c , &task1_evq , NULL ); /* reset the callout to checkin with the sanity task * in 50 seconds to kick off timing. */ os_callout_reset ( &c , TASK1_SANITY_CHECKIN_ITVL ); while ( 1 ) { ev = os_eventq_get ( &task1_evq ); /* The sanity timer has reset */ if ( ev->ev_arg == &c ) { os_sanity_task_checkin ( t ); } else { /* not expecting any other events */ assert ( 0 ); } } /* Should never reach */ assert ( 0 ); }","title":"Checking in with Sanity Task"},{"location":"os/core_os/sanity/sanity/#registering-a-custom-sanity-check","text":"If a particular task wants to further hook into the sanity framework to perform other checks during the sanity task's operation, it can do so by registering a struct os_sanity_check using the os_sanity_check_register function. static int mymodule_perform_sanity_check ( struct os_sanity_check *sc , void *arg ) { /* Perform your checking here. In this case, we check if there * are available buffers in mymodule, and return 0 (all good) * if true, and -1 (error) if not. */ if ( mymodule_has_buffers ()) { return ( 0 ); } else { return ( -1 ); } } static int mymodule_register_sanity_check ( void ) { struct os_sanity_check sc ; os_sanity_check_init ( &sc ); /* Only assert() if mymodule_perform_sanity_check() fails 50 * times. SANITY_TASK_INTERVAL is defined by the user, and * is the frequency at which the sanity_task runs in seconds. */ OS_SANITY_CHECK_SETFUNC ( &sc , mymodule_perform_sanity_check , NULL , 50 * SANITY_TASK_INTERVAL ); rc = os_sanity_check_register ( &sc ); if ( rc != 0 ) { goto err ; } return ( 0 ); err : return ( rc ); } In the above example, every time the custom sanity check mymodule_perform_sanity_check returns successfully (0), the sanity check is reset. In the OS_SANITY_CHECK_SETFUNC macro, the sanity checkin interval is specified as 50 * SANITY_TASK_INTERVAL (which is the interval at which the sanity task runs.) This means that the mymodule_perform_sanity_check() function needs to fail 50 times consecutively before the sanity task will crash the system. TIP: When checking things like memory buffers, which can be temporarily be exhausted, it's a good idea to have the sanity check fail multiple consecutive times before crashing the system. This will avoid crashing for temporary failures.","title":"Registering a Custom Sanity Check"},{"location":"os/core_os/sanity/sanity/#data-structures","text":"","title":"Data structures"},{"location":"os/core_os/sanity/sanity/#os-sanity-check","text":"struct os_sanity_check { os_time_t sc_checkin_last ; os_time_t sc_checkin_itvl ; os_sanity_check_func_t sc_func ; void *sc_arg ; SLIST_ENTRY ( os_sanity_check ) sc_next ; }; Element Description sc_checkin_last The last time this sanity check checked in with the sanity task, in OS time ticks. sc_checkin_itvl How frequently the sanity check is supposed to check in with the sanity task, in OS time ticks. sc_func If not NULL , call this function when running the sanity task. If the function returns 0, reset the sanity check. sc_arg Argument to pass to sc_func when calling it. sc_next Sanity checks are chained in the sanity task when os_sanity_check_register() is called.","title":"OS Sanity Check"},{"location":"os/core_os/sanity/sanity/#list-of-functions","text":"The functions available in sanity are: Function Description os_sanity_check_init Initialize the given sanity check. os_sanity_check_register Register the given sanity check with the sanity task. os_sanity_check_reset Reset the given sanity check. os_sanity_task_checkin Informs the sanity task that the given task is still alive and working normally. os_sanity_task_init Initialize the os sanity task.","title":"List of Functions"},{"location":"os/core_os/semaphore/os_sem_init/","text":"os_sem_init os_error_t os_sem_init ( struct os_sem *sem , uint16_t tokens ) Initialize a semaphore with a given number of tokens. Should be called before the semaphore is used. Arguments Arguments Description *sem Pointer to semaphore tokens Initial number of tokens allocated to semaphore Returned values OS_INVALID_PARM : returned when *sem is NULL on entry. OS_OK : semaphore initialized successfully. Notes Example The following example shows how to initialize a semaphore used for exclusive access. struct os_mutex g_os_sem ; os_error_t err ; err = os_sem_init ( &g_os_sem , 1 ); assert ( err == OS_OK );","title":"os_sem_init"},{"location":"os/core_os/semaphore/os_sem_init/#os_sem_init","text":"os_error_t os_sem_init ( struct os_sem *sem , uint16_t tokens ) Initialize a semaphore with a given number of tokens. Should be called before the semaphore is used.","title":" os_sem_init"},{"location":"os/core_os/semaphore/os_sem_init/#arguments","text":"Arguments Description *sem Pointer to semaphore tokens Initial number of tokens allocated to semaphore","title":"Arguments"},{"location":"os/core_os/semaphore/os_sem_init/#returned-values","text":"OS_INVALID_PARM : returned when *sem is NULL on entry. OS_OK : semaphore initialized successfully.","title":"Returned values"},{"location":"os/core_os/semaphore/os_sem_init/#notes","text":"","title":"Notes"},{"location":"os/core_os/semaphore/os_sem_init/#example","text":"The following example shows how to initialize a semaphore used for exclusive access. struct os_mutex g_os_sem ; os_error_t err ; err = os_sem_init ( &g_os_sem , 1 ); assert ( err == OS_OK );","title":"Example"},{"location":"os/core_os/semaphore/os_sem_pend/","text":"os_sem_pend os_error_t os_sem_pend ( struct os_sem *sem , uint32_t timeout ) Wait for a semaphore for a given amount of time. Arguments Arguments Description *sem Pointer to semaphore timeout Amount of time, in os ticks, to wait for semaphore. A value of 0 means no wait. A value of 0xFFFFFFFF means wait forever. Returned values OS_INVALID_PARM : returned when *sem is NULL on entry. OS_OK : semaphore acquired successfully. OS_TIMEOUT : the semaphore was not available within the timeout specified. OS_NOT_STARTED: Attempt to release a semaphore before os started. Notes If a timeout of 0 is used and the function returns OS_TIMEOUT , the semaphore was not available and was not acquired. No release of the semaphore should occur and the calling task does not own the semaphore. Example struct os_sem g_os_sem ; os_error_t err ; err = os_sem_pend ( &g_os_sem , OS_TIMEOUT_NEVER ); assert ( err == OS_OK ); /* Perform operations requiring semaphore lock */ err = os_sem_release ( &g_os_sem ); assert ( err == OS_OK );","title":"os_sem_pend"},{"location":"os/core_os/semaphore/os_sem_pend/#os_sem_pend","text":"os_error_t os_sem_pend ( struct os_sem *sem , uint32_t timeout ) Wait for a semaphore for a given amount of time.","title":" os_sem_pend "},{"location":"os/core_os/semaphore/os_sem_pend/#arguments","text":"Arguments Description *sem Pointer to semaphore timeout Amount of time, in os ticks, to wait for semaphore. A value of 0 means no wait. A value of 0xFFFFFFFF means wait forever.","title":"Arguments"},{"location":"os/core_os/semaphore/os_sem_pend/#returned-values","text":"OS_INVALID_PARM : returned when *sem is NULL on entry. OS_OK : semaphore acquired successfully. OS_TIMEOUT : the semaphore was not available within the timeout specified. OS_NOT_STARTED: Attempt to release a semaphore before os started.","title":"Returned values"},{"location":"os/core_os/semaphore/os_sem_pend/#notes","text":"If a timeout of 0 is used and the function returns OS_TIMEOUT , the semaphore was not available and was not acquired. No release of the semaphore should occur and the calling task does not own the semaphore.","title":"Notes"},{"location":"os/core_os/semaphore/os_sem_pend/#example","text":"struct os_sem g_os_sem ; os_error_t err ; err = os_sem_pend ( &g_os_sem , OS_TIMEOUT_NEVER ); assert ( err == OS_OK ); /* Perform operations requiring semaphore lock */ err = os_sem_release ( &g_os_sem ); assert ( err == OS_OK );","title":"Example"},{"location":"os/core_os/semaphore/os_sem_release/","text":"os_sem_release os_error_t os_sem_release ( struct os_sem *sem ) Release a semaphore that you are holding. This adds a token to the semaphore. Arguments Arguments Description *sem Pointer to semaphore Returned values OS_NOT_STARTED : Called before os has been started. OS_INVALID_PARM : returned when *sem is NULL on entry. OS_OK : semaphore released successfully. Notes Example struct os_sem g_os_sem ; os_error_t err ; err = os_sem_pend ( &g_os_sem , OS_TIMEOUT_NEVER ); assert ( err == OS_OK ); /* Perform operations requiring semaphore lock */ err = os_sem_release ( &g_os_sem ); assert ( err == OS_OK );","title":"os_sem_release"},{"location":"os/core_os/semaphore/os_sem_release/#os_sem_release","text":"os_error_t os_sem_release ( struct os_sem *sem ) Release a semaphore that you are holding. This adds a token to the semaphore.","title":" os_sem_release "},{"location":"os/core_os/semaphore/os_sem_release/#arguments","text":"Arguments Description *sem Pointer to semaphore","title":"Arguments"},{"location":"os/core_os/semaphore/os_sem_release/#returned-values","text":"OS_NOT_STARTED : Called before os has been started. OS_INVALID_PARM : returned when *sem is NULL on entry. OS_OK : semaphore released successfully.","title":"Returned values"},{"location":"os/core_os/semaphore/os_sem_release/#notes","text":"","title":"Notes"},{"location":"os/core_os/semaphore/os_sem_release/#example","text":"struct os_sem g_os_sem ; os_error_t err ; err = os_sem_pend ( &g_os_sem , OS_TIMEOUT_NEVER ); assert ( err == OS_OK ); /* Perform operations requiring semaphore lock */ err = os_sem_release ( &g_os_sem ); assert ( err == OS_OK );","title":"Example"},{"location":"os/core_os/semaphore/semaphore/","text":"Semaphore A semaphore is a structure used for gaining exclusive access (much like a mutex), synchronizing task operations and/or use in a \"producer/consumer\" roles. Semaphores like the ones used by the Mynewt OS are called \"counting\" semaphores as they are allowed to have more than one token (explained below). Description A semaphore is a fairly simple construct consisting of a queue for waiting tasks and the number of tokens currently owned by the semaphore. A semaphore can be obtained as long as there are tokens in the semaphore. Any task can add tokens to the semaphore and any task can request the semaphore, thereby removing tokens. When creating the semaphore, the initial number of tokens can be set as well. When used for exclusive access to a shared resource the semaphore only needs a single token. In this case, a single task \"creates\" the semaphore by calling os_sem_init with a value of one (1) for the token. When a task desires exclusive access to the shared resource it requests the semaphore by calling os_sem_pend . If there is a token the requesting task will acquire the semaphore and continue operation. If no tokens are available the task will be put to sleep until there is a token. A common problem with using a semaphore for exclusive access is called priority inversion . Consider the following scenario: a high and low priority task both share a resource which is locked using a semaphore. If the low priority task obtains the semaphore and then the high priority task requests the semaphore, the high priority task is now blocked until the low priority task releases the semaphore. Now suppose that there are tasks between the low priority task and the high priority task that want to run. These tasks will preempt the low priority task which owns the semaphore. Thus, the high priority task is blocked waiting for the low priority task to finish using the semaphore but the low priority task cannot run since other tasks are running. Thus, the high priority tasks is \"inverted\" in priority; in effect running at a much lower priority as normally it would preempt the other (lower priority) tasks. If this is an issue a mutex should be used instead of a semaphore. Semaphores can also be used for task synchronization. A simple example of this would be the following. A task creates a semaphore and initializes it with no tokens. The task then waits on the semaphore, and since there are no tokens, the task is put to sleep. When other tasks want to wake up the sleeping task they simply add a token by calling os_sem_release . This will cause the sleeping task to wake up (instantly if no other higher priority tasks want to run). The other common use of a counting semaphore is in what is commonly called a \"producer/consumer\" relationship. The producer adds tokens (by calling os_sem_release ) and the consumer consumes them by calling os_sem_pend . In this relationship, the producer has work for the consumer to do. Each token added to the semaphore will cause the consumer to do whatever work is required. A simple example could be the following: every time a button is pressed there is some work to do (ring a bell). Each button press causes the producer to add a token. Each token consumed rings the bell. There will be exactly the same number of bell rings as there are button presses. In other words, each call to os_sem_pend subtracts exactly one token and each call to os_sem_release adds exactly one token. Data structures struct os_sem { SLIST_HEAD (, os_task ) sem_head ; /* chain of waiting tasks */ uint16_t _pad ; uint16_t sem_tokens ; /* # of tokens */ }; Element Description sem_head Queue head for list of tasks waiting on semaphore _pad Padding for alignment sem_tokens Current number of tokens List of Functions The functions available in semaphore are: Function Description os_sem_init Initialize a semaphore with a given number of tokens. os_sem_pend Wait for a semaphore for a given amount of time. os_sem_release Release a semaphore that you are holding. This adds a token to the semaphore.","title":"toc"},{"location":"os/core_os/semaphore/semaphore/#semaphore","text":"A semaphore is a structure used for gaining exclusive access (much like a mutex), synchronizing task operations and/or use in a \"producer/consumer\" roles. Semaphores like the ones used by the Mynewt OS are called \"counting\" semaphores as they are allowed to have more than one token (explained below).","title":"Semaphore"},{"location":"os/core_os/semaphore/semaphore/#description","text":"A semaphore is a fairly simple construct consisting of a queue for waiting tasks and the number of tokens currently owned by the semaphore. A semaphore can be obtained as long as there are tokens in the semaphore. Any task can add tokens to the semaphore and any task can request the semaphore, thereby removing tokens. When creating the semaphore, the initial number of tokens can be set as well. When used for exclusive access to a shared resource the semaphore only needs a single token. In this case, a single task \"creates\" the semaphore by calling os_sem_init with a value of one (1) for the token. When a task desires exclusive access to the shared resource it requests the semaphore by calling os_sem_pend . If there is a token the requesting task will acquire the semaphore and continue operation. If no tokens are available the task will be put to sleep until there is a token. A common problem with using a semaphore for exclusive access is called priority inversion . Consider the following scenario: a high and low priority task both share a resource which is locked using a semaphore. If the low priority task obtains the semaphore and then the high priority task requests the semaphore, the high priority task is now blocked until the low priority task releases the semaphore. Now suppose that there are tasks between the low priority task and the high priority task that want to run. These tasks will preempt the low priority task which owns the semaphore. Thus, the high priority task is blocked waiting for the low priority task to finish using the semaphore but the low priority task cannot run since other tasks are running. Thus, the high priority tasks is \"inverted\" in priority; in effect running at a much lower priority as normally it would preempt the other (lower priority) tasks. If this is an issue a mutex should be used instead of a semaphore. Semaphores can also be used for task synchronization. A simple example of this would be the following. A task creates a semaphore and initializes it with no tokens. The task then waits on the semaphore, and since there are no tokens, the task is put to sleep. When other tasks want to wake up the sleeping task they simply add a token by calling os_sem_release . This will cause the sleeping task to wake up (instantly if no other higher priority tasks want to run). The other common use of a counting semaphore is in what is commonly called a \"producer/consumer\" relationship. The producer adds tokens (by calling os_sem_release ) and the consumer consumes them by calling os_sem_pend . In this relationship, the producer has work for the consumer to do. Each token added to the semaphore will cause the consumer to do whatever work is required. A simple example could be the following: every time a button is pressed there is some work to do (ring a bell). Each button press causes the producer to add a token. Each token consumed rings the bell. There will be exactly the same number of bell rings as there are button presses. In other words, each call to os_sem_pend subtracts exactly one token and each call to os_sem_release adds exactly one token.","title":"Description"},{"location":"os/core_os/semaphore/semaphore/#data-structures","text":"struct os_sem { SLIST_HEAD (, os_task ) sem_head ; /* chain of waiting tasks */ uint16_t _pad ; uint16_t sem_tokens ; /* # of tokens */ }; Element Description sem_head Queue head for list of tasks waiting on semaphore _pad Padding for alignment sem_tokens Current number of tokens","title":"Data structures"},{"location":"os/core_os/semaphore/semaphore/#list-of-functions","text":"The functions available in semaphore are: Function Description os_sem_init Initialize a semaphore with a given number of tokens. os_sem_pend Wait for a semaphore for a given amount of time. os_sem_release Release a semaphore that you are holding. This adds a token to the semaphore.","title":"List of Functions"},{"location":"os/core_os/task/os_task_count/","text":"os_task_count uint8_t os_task_count ( void ); Returns the number of tasks that have been created. Arguments None Returned values unsigned 8-bit integer representing number of tasks created Example uint8_t num_tasks ; num_tasks = os_task_count ();","title":"os_task_count"},{"location":"os/core_os/task/os_task_count/#os_task_count","text":"uint8_t os_task_count ( void ); Returns the number of tasks that have been created.","title":" os_task_count"},{"location":"os/core_os/task/os_task_count/#arguments","text":"None","title":"Arguments"},{"location":"os/core_os/task/os_task_count/#returned-values","text":"unsigned 8-bit integer representing number of tasks created","title":"Returned values"},{"location":"os/core_os/task/os_task_count/#example","text":"uint8_t num_tasks ; num_tasks = os_task_count ();","title":"Example"},{"location":"os/core_os/task/os_task_info_get_next/","text":"os_task_info_get_next struct os_task *os_task_info_get_next ( const struct os_task *prev , struct os_task_info *oti ); Populates the os task info structure pointed to by oti with task information. The task populating the oti structure is either the first task on the task list if prev is NULL , or the next task in the task list (the next pointer of prev ). If there are no tasks initialized, NULL is returned. Otherwise, the task structure used to populate oti is returned. Arguments Arguments Description prev Pointer to previous task in task list. If NULL, use first task on list oti Pointer to os_task_info structure where task information will be stored Returned values Returns a pointer to the os task structure that was used to populate the task information structure. NULL means that no tasks were created. Example void get_task_info ( void ) { struct os_task *prev_task ; struct os_task_info oti ; console_printf ( \"Tasks: \\n\" ); prev_task = NULL ; while ( 1 ) { prev_task = os_task_info_get_next ( prev_task , &oti ); if ( prev_task == NULL ) { break ; } console_printf ( \" %s (prio: %u, tid: %u, lcheck: %lu, ncheck: %lu, \" \"flags: 0x%x, ssize: %u, susage: %u, cswcnt: %lu, \" \"tot_run_time: %lums)\\n\" , oti . oti_name , oti . oti_prio , oti . oti_taskid , ( unsigned long ) oti . oti_last_checkin , ( unsigned long ) oti . oti_next_checkin , oti . oti_flags , oti . oti_stksize , oti . oti_stkusage , ( unsigned long ) oti . oti_cswcnt , ( unsigned long ) oti . oti_runtime ); } }","title":"os_task_info_get_next"},{"location":"os/core_os/task/os_task_info_get_next/#os_task_info_get_next","text":"struct os_task *os_task_info_get_next ( const struct os_task *prev , struct os_task_info *oti ); Populates the os task info structure pointed to by oti with task information. The task populating the oti structure is either the first task on the task list if prev is NULL , or the next task in the task list (the next pointer of prev ). If there are no tasks initialized, NULL is returned. Otherwise, the task structure used to populate oti is returned.","title":" os_task_info_get_next"},{"location":"os/core_os/task/os_task_info_get_next/#arguments","text":"Arguments Description prev Pointer to previous task in task list. If NULL, use first task on list oti Pointer to os_task_info structure where task information will be stored","title":"Arguments"},{"location":"os/core_os/task/os_task_info_get_next/#returned-values","text":"Returns a pointer to the os task structure that was used to populate the task information structure. NULL means that no tasks were created.","title":"Returned values"},{"location":"os/core_os/task/os_task_info_get_next/#example","text":"void get_task_info ( void ) { struct os_task *prev_task ; struct os_task_info oti ; console_printf ( \"Tasks: \\n\" ); prev_task = NULL ; while ( 1 ) { prev_task = os_task_info_get_next ( prev_task , &oti ); if ( prev_task == NULL ) { break ; } console_printf ( \" %s (prio: %u, tid: %u, lcheck: %lu, ncheck: %lu, \" \"flags: 0x%x, ssize: %u, susage: %u, cswcnt: %lu, \" \"tot_run_time: %lums)\\n\" , oti . oti_name , oti . oti_prio , oti . oti_taskid , ( unsigned long ) oti . oti_last_checkin , ( unsigned long ) oti . oti_next_checkin , oti . oti_flags , oti . oti_stksize , oti . oti_stkusage , ( unsigned long ) oti . oti_cswcnt , ( unsigned long ) oti . oti_runtime ); } }","title":"Example"},{"location":"os/core_os/task/os_task_init/","text":"os_task_init int os_task_init ( struct os_task *t , char *name , os_task_func_t func , void *arg , uint8_t prio , os_time_t sanity_itvl , os_stack_t *stack_bottom , uint16_t stack_size ) Called to create a task. This adds the task object to the list of ready to run tasks. Arguments Arguments Description t Pointer to task name Task name func Task function arg Generic argument to pass to task prio Priority of task sanity_itvl The interval at which the sanity task will check to see if this task is sill alive stack_bottom Pointer to bottom of stack. stack_size The size of the stack. NOTE: this is not in bytes! It is the number of os_stack_t elements allocated (generally 32-bits each) Returned values OS_OK : task initialization successful. All other error codes indicate an internal error. Example /* Create the task */ int rc ; os_stack_t my_task_stack [ MY_STACK_SIZE ]; rc = os_task_init ( &my_task , \"my_task\" , my_task_func , NULL , MY_TASK_PRIO , OS_WAIT_FOREVER , my_task_stack , MY_STACK_SIZE ); assert ( rc == OS_OK );","title":"os_task_init"},{"location":"os/core_os/task/os_task_init/#os_task_init","text":"int os_task_init ( struct os_task *t , char *name , os_task_func_t func , void *arg , uint8_t prio , os_time_t sanity_itvl , os_stack_t *stack_bottom , uint16_t stack_size ) Called to create a task. This adds the task object to the list of ready to run tasks.","title":" os_task_init"},{"location":"os/core_os/task/os_task_init/#arguments","text":"Arguments Description t Pointer to task name Task name func Task function arg Generic argument to pass to task prio Priority of task sanity_itvl The interval at which the sanity task will check to see if this task is sill alive stack_bottom Pointer to bottom of stack. stack_size The size of the stack. NOTE: this is not in bytes! It is the number of os_stack_t elements allocated (generally 32-bits each)","title":"Arguments"},{"location":"os/core_os/task/os_task_init/#returned-values","text":"OS_OK : task initialization successful. All other error codes indicate an internal error.","title":"Returned values"},{"location":"os/core_os/task/os_task_init/#example","text":"/* Create the task */ int rc ; os_stack_t my_task_stack [ MY_STACK_SIZE ]; rc = os_task_init ( &my_task , \"my_task\" , my_task_func , NULL , MY_TASK_PRIO , OS_WAIT_FOREVER , my_task_stack , MY_STACK_SIZE ); assert ( rc == OS_OK );","title":"Example"},{"location":"os/core_os/task/os_task_remove/","text":"os_task_remove int os_task_remove ( struct os_task *t ) Removes a task, t , from the task list. A task cannot be removed when it is in one of the following states: It is running - a task cannot remove itself. It has not been initialized. It is holding a lock on a semphore or mutex. It is suspended waiting on a lock (semaphore or mutex) or for an event on an event queue. Arguments Arguments Description t Pointer to the os_task structure for the task to be removed Returned values OS_OK : Task t is removed sucessfully. OS_INVALID_PARM : Task t is the calling task. A task cannot remove itself. OS_NOT_STARTED : Task t is not initialized. OS_EBUSY : Task t is either holding a lock or suspended waiting for a lock or an event. Example struct os_task worker_task ; int remove_my_worker_task ( void ) { /* Add error checking code to ensure task can removed. */ /* Call os_task_remove to remove the worker task */ rc = os_task_remove ( &worker_task ); return rc ; }","title":"os_task_remove"},{"location":"os/core_os/task/os_task_remove/#os_task_remove","text":"int os_task_remove ( struct os_task *t ) Removes a task, t , from the task list. A task cannot be removed when it is in one of the following states: It is running - a task cannot remove itself. It has not been initialized. It is holding a lock on a semphore or mutex. It is suspended waiting on a lock (semaphore or mutex) or for an event on an event queue.","title":" os_task_remove"},{"location":"os/core_os/task/os_task_remove/#arguments","text":"Arguments Description t Pointer to the os_task structure for the task to be removed","title":"Arguments"},{"location":"os/core_os/task/os_task_remove/#returned-values","text":"OS_OK : Task t is removed sucessfully. OS_INVALID_PARM : Task t is the calling task. A task cannot remove itself. OS_NOT_STARTED : Task t is not initialized. OS_EBUSY : Task t is either holding a lock or suspended waiting for a lock or an event.","title":"Returned values"},{"location":"os/core_os/task/os_task_remove/#example","text":"struct os_task worker_task ; int remove_my_worker_task ( void ) { /* Add error checking code to ensure task can removed. */ /* Call os_task_remove to remove the worker task */ rc = os_task_remove ( &worker_task ); return rc ; }","title":"Example"},{"location":"os/core_os/task/task/","text":"Task A task, along with the scheduler, forms the basis of the Mynewt OS. A task consists of two basic elements: a task stack and a task function. The task function is basically a forever loop, waiting for some \"event\" to wake it up. There are two methods used to signal a task that it has work to do: event queues and semaphores . The Mynewt OS is a multi-tasking, preemptive OS. Every task is assigned a task priority (from 0 to 255), with 0 being the highest priority task. If a higher priority task than the current task wants to run, the scheduler preempts the currently running task and switches context to the higher priority task. This is just a fancy way of saying that the processor stack pointer now points to the stack of the higher priority task and the task resumes execution where it left off. Tasks run to completion unless they are preempted by a higher priority task. The developer must ensure that tasks eventually \"sleep\"; otherwise lower priority tasks will never get a chance to run (actually, any task lower in priority than the task that never sleeps). A task will be put to sleep in the following cases: it puts itself to sleep using os_time_delay() , it waits on an event queue which is empty or attempts to obtain a mutex or a semaphore that is currently owned by another task. Note that other sections of the manual describe these OS features in more detail. Description In order to create a task two data structures need to be defined: the task object ( struct os_task ) and its associated stack. Determining the stack size can be a bit tricky; generally developers should not declare large local variables on the stack so that task stacks can be of limited size. However, all applications are different and the developer must choose the stack size accordingly. NOTE: be careful when declaring your stack! The stack is in units of os_stack_t sized elements (generally 32-bits). Looking at the example given below and assuming os_stack_t is defined to be a 32-bit unsigned value, \"my_task_stack\" will use 256 bytes. A task must also have an associated \"task function\". This is the function that will be called when the task is first run. This task function should never return! In order to inform the Mynewt OS of the new task and to have it added to the scheduler, the os_task_init() function is called. Once os_task_init() is called, the task is made ready to run and is added to the active task list. Note that a task can be initialized (started) before or after the os has started (i.e. before os_start() is called) but must be initialized after the os has been initialized (i.e. 'os_init()' has been called). In most of the examples and current Mynewt projects, the os is initialized, tasks are initialized, and the the os is started. Once the os has started, the highest priority task will be the first task set to run. Information about a task can be obtained using the os_task_info_get_next() API. Developers can walk the list of tasks to obtain information on all created tasks. This information is of type os_task_info and is described below. The following is a very simple example showing a single application task. This task simply toggles an LED at a one second interval. /* Create a simple \"project\" with a task that blinks a LED every second */ /* Define task stack and task object */ #define MY_TASK_PRI (OS_TASK_PRI_HIGHEST) #define MY_STACK_SIZE (64) struct os_task my_task ; os_stack_t my_task_stack [ MY_STACK_SIZE ]; /* This is the task function */ void my_task_func ( void *arg ) { /* Set the led pin as an output */ hal_gpio_init_out ( LED_BLINK_PIN , 1 ); /* The task is a forever loop that does not return */ while ( 1 ) { /* Wait one second */ os_time_delay ( 1000 ); /* Toggle the LED */ hal_gpio_toggle ( LED_BLINK_PIN ); } } /* This is the main function for the project */ int main ( int argc , char **argv ) { /* Perform system and package initialization */ sysinit (); /* Initialize the task */ os_task_init ( &my_task , \"my_task\" , my_task_func , NULL , MY_TASK_PRIO , OS_WAIT_FOREVER , my_task_stack , MY_STACK_SIZE ); /* Process events from the default event queue. */ while ( 1 ) { os_eventq_run ( os_eventq_dflt_get ()); } /* main never returns */ } Data structures /* The highest and lowest task priorities */ #define OS_TASK_PRI_HIGHEST (0) #define OS_TASK_PRI_LOWEST (0xff) /* Task states */ typedef enum os_task_state { OS_TASK_READY = 1 , OS_TASK_SLEEP = 2 } os_task_state_t ; /* Task flags */ #define OS_TASK_FLAG_NO_TIMEOUT (0x0001U) #define OS_TASK_FLAG_SEM_WAIT (0x0002U) #define OS_TASK_FLAG_MUTEX_WAIT (0x0004U) typedef void ( *os_task_func_t )( void * ); #define OS_TASK_MAX_NAME_LEN (32) struct os_task { os_stack_t *t_stackptr ; os_stack_t *t_stacktop ; uint16_t t_stacksize ; uint16_t t_flags ; uint8_t t_taskid ; uint8_t t_prio ; uint8_t t_state ; uint8_t t_pad ; char *t_name ; os_task_func_t t_func ; void *t_arg ; void *t_obj ; struct os_sanity_check t_sanity_check ; os_time_t t_next_wakeup ; os_time_t t_run_time ; uint32_t t_ctx_sw_cnt ; /* Global list of all tasks, irrespective of run or sleep lists */ STAILQ_ENTRY ( os_task ) t_os_task_list ; /* Used to chain task to either the run or sleep list */ TAILQ_ENTRY ( os_task ) t_os_list ; /* Used to chain task to an object such as a semaphore or mutex */ SLIST_ENTRY ( os_task ) t_obj_list ; }; Element Description t_stackptr Current stack pointer t_stacktop The address of the top of the task stack. The stack grows downward t_stacksize The size of the stack, in units of os_stack_t (not bytes!) t_flags Task flags (see flag definitions) t_taskid A numeric id assigned to each task t_prio The priority of the task. The lower the number, the higher the priority t_state The task state (see state definitions) t_pad padding (for alignment) t_name Name of task t_func Pointer to task function t_obj Generic object used by mutexes and semaphores when the task is waiting on a mutex or semaphore t_sanity_check Sanity task data structure t_next_wakeup OS time when task is next scheduled to wake up t_run_time The amount of os time ticks this task has been running t_ctx_sw_cnt The number of times that this task has been run t_os_task_list List pointer for global task list. All tasks are placed on this list t_os_list List pointer used by either the active task list or the sleeping task list t_obj_list List pointer for tasks waiting on a semaphore or mutex struct os_task_info { uint8_t oti_prio ; uint8_t oti_taskid ; uint8_t oti_state ; uint8_t oti_flags ; uint16_t oti_stkusage ; uint16_t oti_stksize ; uint32_t oti_cswcnt ; uint32_t oti_runtime ; os_time_t oti_last_checkin ; os_time_t oti_next_checkin ; char oti_name [ OS_TASK_MAX_NAME_LEN ]; }; Element Description oti_prio Task priority oti_taskid Task id oti_state Task state oti_flags Task flags oti_stkusage Amount of stack used by the task (in os_stack_t units) oti_stksize The size of the stack (in os_stack_t units) oti_cswcnt The context switch count oti_runtime The amount of time that the task has run (in os time ticks) oti_last_checkin The time (os time) at which this task last checked in to the sanity task oti_next_checkin The time (os time) at which this task last checked in to the sanity task oti_name Name of the task List of Functions The functions available in task are: Function Description os_task_init Called to create a task. This adds the task object to the list of ready to run tasks. os_task_count Returns the number of tasks that have been created. os_task_info_get_next Populates the os task info structure given with task information. os_task_remove Removes a task from the task list.","title":"toc"},{"location":"os/core_os/task/task/#task","text":"A task, along with the scheduler, forms the basis of the Mynewt OS. A task consists of two basic elements: a task stack and a task function. The task function is basically a forever loop, waiting for some \"event\" to wake it up. There are two methods used to signal a task that it has work to do: event queues and semaphores . The Mynewt OS is a multi-tasking, preemptive OS. Every task is assigned a task priority (from 0 to 255), with 0 being the highest priority task. If a higher priority task than the current task wants to run, the scheduler preempts the currently running task and switches context to the higher priority task. This is just a fancy way of saying that the processor stack pointer now points to the stack of the higher priority task and the task resumes execution where it left off. Tasks run to completion unless they are preempted by a higher priority task. The developer must ensure that tasks eventually \"sleep\"; otherwise lower priority tasks will never get a chance to run (actually, any task lower in priority than the task that never sleeps). A task will be put to sleep in the following cases: it puts itself to sleep using os_time_delay() , it waits on an event queue which is empty or attempts to obtain a mutex or a semaphore that is currently owned by another task. Note that other sections of the manual describe these OS features in more detail.","title":"Task"},{"location":"os/core_os/task/task/#description","text":"In order to create a task two data structures need to be defined: the task object ( struct os_task ) and its associated stack. Determining the stack size can be a bit tricky; generally developers should not declare large local variables on the stack so that task stacks can be of limited size. However, all applications are different and the developer must choose the stack size accordingly. NOTE: be careful when declaring your stack! The stack is in units of os_stack_t sized elements (generally 32-bits). Looking at the example given below and assuming os_stack_t is defined to be a 32-bit unsigned value, \"my_task_stack\" will use 256 bytes. A task must also have an associated \"task function\". This is the function that will be called when the task is first run. This task function should never return! In order to inform the Mynewt OS of the new task and to have it added to the scheduler, the os_task_init() function is called. Once os_task_init() is called, the task is made ready to run and is added to the active task list. Note that a task can be initialized (started) before or after the os has started (i.e. before os_start() is called) but must be initialized after the os has been initialized (i.e. 'os_init()' has been called). In most of the examples and current Mynewt projects, the os is initialized, tasks are initialized, and the the os is started. Once the os has started, the highest priority task will be the first task set to run. Information about a task can be obtained using the os_task_info_get_next() API. Developers can walk the list of tasks to obtain information on all created tasks. This information is of type os_task_info and is described below. The following is a very simple example showing a single application task. This task simply toggles an LED at a one second interval. /* Create a simple \"project\" with a task that blinks a LED every second */ /* Define task stack and task object */ #define MY_TASK_PRI (OS_TASK_PRI_HIGHEST) #define MY_STACK_SIZE (64) struct os_task my_task ; os_stack_t my_task_stack [ MY_STACK_SIZE ]; /* This is the task function */ void my_task_func ( void *arg ) { /* Set the led pin as an output */ hal_gpio_init_out ( LED_BLINK_PIN , 1 ); /* The task is a forever loop that does not return */ while ( 1 ) { /* Wait one second */ os_time_delay ( 1000 ); /* Toggle the LED */ hal_gpio_toggle ( LED_BLINK_PIN ); } } /* This is the main function for the project */ int main ( int argc , char **argv ) { /* Perform system and package initialization */ sysinit (); /* Initialize the task */ os_task_init ( &my_task , \"my_task\" , my_task_func , NULL , MY_TASK_PRIO , OS_WAIT_FOREVER , my_task_stack , MY_STACK_SIZE ); /* Process events from the default event queue. */ while ( 1 ) { os_eventq_run ( os_eventq_dflt_get ()); } /* main never returns */ }","title":"Description"},{"location":"os/core_os/task/task/#data-structures","text":"/* The highest and lowest task priorities */ #define OS_TASK_PRI_HIGHEST (0) #define OS_TASK_PRI_LOWEST (0xff) /* Task states */ typedef enum os_task_state { OS_TASK_READY = 1 , OS_TASK_SLEEP = 2 } os_task_state_t ; /* Task flags */ #define OS_TASK_FLAG_NO_TIMEOUT (0x0001U) #define OS_TASK_FLAG_SEM_WAIT (0x0002U) #define OS_TASK_FLAG_MUTEX_WAIT (0x0004U) typedef void ( *os_task_func_t )( void * ); #define OS_TASK_MAX_NAME_LEN (32) struct os_task { os_stack_t *t_stackptr ; os_stack_t *t_stacktop ; uint16_t t_stacksize ; uint16_t t_flags ; uint8_t t_taskid ; uint8_t t_prio ; uint8_t t_state ; uint8_t t_pad ; char *t_name ; os_task_func_t t_func ; void *t_arg ; void *t_obj ; struct os_sanity_check t_sanity_check ; os_time_t t_next_wakeup ; os_time_t t_run_time ; uint32_t t_ctx_sw_cnt ; /* Global list of all tasks, irrespective of run or sleep lists */ STAILQ_ENTRY ( os_task ) t_os_task_list ; /* Used to chain task to either the run or sleep list */ TAILQ_ENTRY ( os_task ) t_os_list ; /* Used to chain task to an object such as a semaphore or mutex */ SLIST_ENTRY ( os_task ) t_obj_list ; }; Element Description t_stackptr Current stack pointer t_stacktop The address of the top of the task stack. The stack grows downward t_stacksize The size of the stack, in units of os_stack_t (not bytes!) t_flags Task flags (see flag definitions) t_taskid A numeric id assigned to each task t_prio The priority of the task. The lower the number, the higher the priority t_state The task state (see state definitions) t_pad padding (for alignment) t_name Name of task t_func Pointer to task function t_obj Generic object used by mutexes and semaphores when the task is waiting on a mutex or semaphore t_sanity_check Sanity task data structure t_next_wakeup OS time when task is next scheduled to wake up t_run_time The amount of os time ticks this task has been running t_ctx_sw_cnt The number of times that this task has been run t_os_task_list List pointer for global task list. All tasks are placed on this list t_os_list List pointer used by either the active task list or the sleeping task list t_obj_list List pointer for tasks waiting on a semaphore or mutex struct os_task_info { uint8_t oti_prio ; uint8_t oti_taskid ; uint8_t oti_state ; uint8_t oti_flags ; uint16_t oti_stkusage ; uint16_t oti_stksize ; uint32_t oti_cswcnt ; uint32_t oti_runtime ; os_time_t oti_last_checkin ; os_time_t oti_next_checkin ; char oti_name [ OS_TASK_MAX_NAME_LEN ]; }; Element Description oti_prio Task priority oti_taskid Task id oti_state Task state oti_flags Task flags oti_stkusage Amount of stack used by the task (in os_stack_t units) oti_stksize The size of the stack (in os_stack_t units) oti_cswcnt The context switch count oti_runtime The amount of time that the task has run (in os time ticks) oti_last_checkin The time (os time) at which this task last checked in to the sanity task oti_next_checkin The time (os time) at which this task last checked in to the sanity task oti_name Name of the task","title":"Data structures"},{"location":"os/core_os/task/task/#list-of-functions","text":"The functions available in task are: Function Description os_task_init Called to create a task. This adds the task object to the list of ready to run tasks. os_task_count Returns the number of tasks that have been created. os_task_info_get_next Populates the os task info structure given with task information. os_task_remove Removes a task from the task list.","title":"List of Functions"},{"location":"os/core_os/time/os_get_uptime_usec/","text":"os_get_uptime_usec int64_t os_get_uptime_usec ( void ) Gets the time duration, in microseconds, since boot. Arguments N/A Returned values Time since boot in microseconds. Notes Example int64_t time_since_boot ; time_since_boot = os_get_uptime_usec ();","title":"os_get_uptime_usec"},{"location":"os/core_os/time/os_get_uptime_usec/#os_get_uptime_usec","text":"int64_t os_get_uptime_usec ( void ) Gets the time duration, in microseconds, since boot.","title":"os_get_uptime_usec"},{"location":"os/core_os/time/os_get_uptime_usec/#arguments","text":"N/A","title":"Arguments"},{"location":"os/core_os/time/os_get_uptime_usec/#returned-values","text":"Time since boot in microseconds.","title":"Returned values"},{"location":"os/core_os/time/os_get_uptime_usec/#notes","text":"","title":"Notes"},{"location":"os/core_os/time/os_get_uptime_usec/#example","text":"int64_t time_since_boot ; time_since_boot = os_get_uptime_usec ();","title":"Example"},{"location":"os/core_os/time/os_gettimeofday/","text":"os_gettimeofday int os_gettimeofday ( struct os_timeval *utctime , struct os_timezone *timezone ); Arguments Arguments Description utctime UTC time corresponding to wallclock time timezone Timezone to convert UTC time to wallclock time Returned values Returns 0 on success and non-zero on failure. Notes utctime or timezone may be NULL. The function is a no-op if both utctime and timezone are NULL. Example /* * Display wallclock time on the console. */ int rc ; struct os_timeval utc ; struct os_timezone tz ; char buf [ DATETIME_BUFSIZE ]; rc = os_gettimeofday ( &utc , &tz ); if ( rc == 0 ) { format_datetime ( &utc , &tz , buf , sizeof ( buf )); console_printf ( \"%s\\n\" , buf ); }","title":"os_gettimeofday"},{"location":"os/core_os/time/os_gettimeofday/#os_gettimeofday","text":"int os_gettimeofday ( struct os_timeval *utctime , struct os_timezone *timezone );","title":"os_gettimeofday"},{"location":"os/core_os/time/os_gettimeofday/#arguments","text":"Arguments Description utctime UTC time corresponding to wallclock time timezone Timezone to convert UTC time to wallclock time","title":"Arguments"},{"location":"os/core_os/time/os_gettimeofday/#returned-values","text":"Returns 0 on success and non-zero on failure.","title":"Returned values"},{"location":"os/core_os/time/os_gettimeofday/#notes","text":"utctime or timezone may be NULL. The function is a no-op if both utctime and timezone are NULL.","title":"Notes"},{"location":"os/core_os/time/os_gettimeofday/#example","text":"/* * Display wallclock time on the console. */ int rc ; struct os_timeval utc ; struct os_timezone tz ; char buf [ DATETIME_BUFSIZE ]; rc = os_gettimeofday ( &utc , &tz ); if ( rc == 0 ) { format_datetime ( &utc , &tz , buf , sizeof ( buf )); console_printf ( \"%s\\n\" , buf ); }","title":"Example"},{"location":"os/core_os/time/os_settimeofday/","text":"os_settimeofday int os_settimeofday ( struct os_timeval *utctime , struct os_timezone *timezone ); Arguments Arguments Description utctime UTC time corresponding to the wallclock time timezone Timezone associated with the wallclock time Returned values Returns 0 on success and non-zero on failure. Notes utctime may be NULL if only the timezone needs to be changed. This is useful when adjusting the timezone to account for daylight savings. timezone may be NULL if only the UTC time needs to be changed. This is useful when synchronizing Mynewt's time with an external time source like NTP. The function is a no-op if both utctime and timezone are NULL. Example int rc ; parse_datetime ( datestr , &utctime , &tz ); rc = os_settimeofday ( &utctime , &tz ); if ( rc == 0 ) { /* success */ }","title":"os_settimeofday"},{"location":"os/core_os/time/os_settimeofday/#os_settimeofday","text":"int os_settimeofday ( struct os_timeval *utctime , struct os_timezone *timezone );","title":"os_settimeofday"},{"location":"os/core_os/time/os_settimeofday/#arguments","text":"Arguments Description utctime UTC time corresponding to the wallclock time timezone Timezone associated with the wallclock time","title":"Arguments"},{"location":"os/core_os/time/os_settimeofday/#returned-values","text":"Returns 0 on success and non-zero on failure.","title":"Returned values"},{"location":"os/core_os/time/os_settimeofday/#notes","text":"utctime may be NULL if only the timezone needs to be changed. This is useful when adjusting the timezone to account for daylight savings. timezone may be NULL if only the UTC time needs to be changed. This is useful when synchronizing Mynewt's time with an external time source like NTP. The function is a no-op if both utctime and timezone are NULL.","title":"Notes"},{"location":"os/core_os/time/os_settimeofday/#example","text":"int rc ; parse_datetime ( datestr , &utctime , &tz ); rc = os_settimeofday ( &utctime , &tz ); if ( rc == 0 ) { /* success */ }","title":"Example"},{"location":"os/core_os/time/os_time/","text":"OS_Time The system time for the Mynewt OS. Description The Mynewt OS contains an incrementing time that drives the OS scheduler and time delays. The time is a fixed size (e.g. 32 bits) and will eventually wrap back to zero. The time to wrap from zero back to zero is called the OS time epoch . The frequency of the OS time tick is specified in the architecture-specific OS code os_arch.h and is named OS_TICKS_PER_SEC . The Mynewt OS also provides APIs for setting and retrieving the wallclock time (also known as local time or time-of-day in other operating systems). Data Structures Time is stored in Mynewt as an os_time_t value. Wallclock time is represented using the struct os_timeval and struct os_timezone tuple. struct os_timeval represents the number of seconds elapsed since the epoch (00:00:00 Jan 1, 1970 UTC). struct os_timeval { int64_t tv_sec ; /* seconds since Jan 1 1970 UTC */ int32_t tv_usec ; /* fractional seconds */ }; struct os_timeval tv = { 1457400000 , 0 }; /* 01:20:00 Mar 8 2016 UTC */ struct os_timezone is used to specify the offset of local time from UTC and whether daylight savings is in effect. Note that tz_minuteswest is a positive number if the local time is behind UTC and a negative number if the local time is ahead of UTC. struct os_timezone { int16_t tz_minuteswest ; int16_t tz_dsttime ; }; /* Pacific Standard Time is 08:00 hours west of UTC */ struct os_timezone PST = { 480 , 0 }; struct os_timezone PDT = { 480 , 1 }; /* Indian Standard Time is 05:30 hours east of UTC */ struct os_timezone IST = { -330 , 0 }; List of Functions The functions available in time are: Function Description os_time_advance Increments the OS time tick for the system. os_time_delay Put the current task to sleep for the given number of ticks. os_time_get Get the current value of OS time. os_time_ms_to_ticks Converts milliseconds to os ticks. os_get_uptime_usec Gets the time duration since boot. os_gettimeofday Populate the given timeval and timezone structs with current time data. os_settimeofday Set the current time of day to the given time structs. List of Macros Several macros help with the evalution of times with respect to each other. OS_TIME_TICK_LT(t1,t2) -- evaluates to true if t1 is before t2 in time. OS_TIME_TICK_GT(t1,t2) -- evaluates to true if t1 is after t2 in time OS_TIME_TICK_GEQ(t1,t2) -- evaluates to true if t1 is on or after t2 in time. NOTE: For all of these macros the calculations are done modulo 'os_time_t'. Ensure that comparison of OS time always uses the macros above (to compensate for the possible wrap of OS time). The following macros help adding or subtracting time when represented as struct os_timeval . All parameters to the following macros are pointers to struct os_timeval . os_timeradd(tvp, uvp, vvp) -- Add uvp to tvp and store result in vvp . os_timersub(tvp, uvp, vvp) -- Subtract uvp from tvp and store result in vvp . Special Notes Its important to understand how quickly the time wraps especially when doing time comparison using the macros above (or by any other means). For example, if a tick is 1 millisecond and os_time_t is 32-bits the OS time will wrap back to zero in about 49.7 days or stated another way, the OS time epoch is 49.7 days. If two times are more than 1/2 the OS time epoch apart, any time comparison will be incorrect. Ensure at design time that comparisons will not occur between times that are more than half the OS time epoch.","title":"toc"},{"location":"os/core_os/time/os_time/#os_time","text":"The system time for the Mynewt OS.","title":"OS_Time"},{"location":"os/core_os/time/os_time/#description","text":"The Mynewt OS contains an incrementing time that drives the OS scheduler and time delays. The time is a fixed size (e.g. 32 bits) and will eventually wrap back to zero. The time to wrap from zero back to zero is called the OS time epoch . The frequency of the OS time tick is specified in the architecture-specific OS code os_arch.h and is named OS_TICKS_PER_SEC . The Mynewt OS also provides APIs for setting and retrieving the wallclock time (also known as local time or time-of-day in other operating systems).","title":"Description"},{"location":"os/core_os/time/os_time/#data-structures","text":"Time is stored in Mynewt as an os_time_t value. Wallclock time is represented using the struct os_timeval and struct os_timezone tuple. struct os_timeval represents the number of seconds elapsed since the epoch (00:00:00 Jan 1, 1970 UTC). struct os_timeval { int64_t tv_sec ; /* seconds since Jan 1 1970 UTC */ int32_t tv_usec ; /* fractional seconds */ }; struct os_timeval tv = { 1457400000 , 0 }; /* 01:20:00 Mar 8 2016 UTC */ struct os_timezone is used to specify the offset of local time from UTC and whether daylight savings is in effect. Note that tz_minuteswest is a positive number if the local time is behind UTC and a negative number if the local time is ahead of UTC. struct os_timezone { int16_t tz_minuteswest ; int16_t tz_dsttime ; }; /* Pacific Standard Time is 08:00 hours west of UTC */ struct os_timezone PST = { 480 , 0 }; struct os_timezone PDT = { 480 , 1 }; /* Indian Standard Time is 05:30 hours east of UTC */ struct os_timezone IST = { -330 , 0 };","title":"Data Structures"},{"location":"os/core_os/time/os_time/#list-of-functions","text":"The functions available in time are: Function Description os_time_advance Increments the OS time tick for the system. os_time_delay Put the current task to sleep for the given number of ticks. os_time_get Get the current value of OS time. os_time_ms_to_ticks Converts milliseconds to os ticks. os_get_uptime_usec Gets the time duration since boot. os_gettimeofday Populate the given timeval and timezone structs with current time data. os_settimeofday Set the current time of day to the given time structs.","title":"List of Functions"},{"location":"os/core_os/time/os_time/#list-of-macros","text":"Several macros help with the evalution of times with respect to each other. OS_TIME_TICK_LT(t1,t2) -- evaluates to true if t1 is before t2 in time. OS_TIME_TICK_GT(t1,t2) -- evaluates to true if t1 is after t2 in time OS_TIME_TICK_GEQ(t1,t2) -- evaluates to true if t1 is on or after t2 in time. NOTE: For all of these macros the calculations are done modulo 'os_time_t'. Ensure that comparison of OS time always uses the macros above (to compensate for the possible wrap of OS time). The following macros help adding or subtracting time when represented as struct os_timeval . All parameters to the following macros are pointers to struct os_timeval . os_timeradd(tvp, uvp, vvp) -- Add uvp to tvp and store result in vvp . os_timersub(tvp, uvp, vvp) -- Subtract uvp from tvp and store result in vvp .","title":"List of Macros"},{"location":"os/core_os/time/os_time/#special-notes","text":"Its important to understand how quickly the time wraps especially when doing time comparison using the macros above (or by any other means). For example, if a tick is 1 millisecond and os_time_t is 32-bits the OS time will wrap back to zero in about 49.7 days or stated another way, the OS time epoch is 49.7 days. If two times are more than 1/2 the OS time epoch apart, any time comparison will be incorrect. Ensure at design time that comparisons will not occur between times that are more than half the OS time epoch.","title":"Special Notes"},{"location":"os/core_os/time/os_time_advance/","text":"os_time_advance void os_time_advance ( int ticks ) Moves the OS time forward by the value specified in ticks . Typically, this is called in one place by the architecture specific OS code (kernel/os/src/arch) timer_handler which is in turn called by the BSP specific code assigned to drive the OS timer tick. See Porting Mynewt OS for details. Arguments Arguments Description ticks Number of ticks to move the OS time forward. Returned values N/A Notes Example","title":"os_time_advance"},{"location":"os/core_os/time/os_time_advance/#os_time_advance","text":"void os_time_advance ( int ticks ) Moves the OS time forward by the value specified in ticks . Typically, this is called in one place by the architecture specific OS code (kernel/os/src/arch) timer_handler which is in turn called by the BSP specific code assigned to drive the OS timer tick. See Porting Mynewt OS for details.","title":"os_time_advance"},{"location":"os/core_os/time/os_time_advance/#arguments","text":"Arguments Description ticks Number of ticks to move the OS time forward.","title":"Arguments"},{"location":"os/core_os/time/os_time_advance/#returned-values","text":"N/A","title":"Returned values"},{"location":"os/core_os/time/os_time_advance/#notes","text":"","title":"Notes"},{"location":"os/core_os/time/os_time_advance/#example","text":"","title":"Example"},{"location":"os/core_os/time/os_time_delay/","text":"os_time_delay void os_time_delay ( int32_t ticks ) Arguments Arguments Description ticks Number of ticks to delay. Less than or equal to zero means no delay Returned values N/A Notes Passing OS_TIMEOUT_NEVER to this function will not block indefinitely but will return immediately. Passing delays larger than 1/2 the OS time epoch should be avoided; behavior is unpredictable. Example /* delay 3 seconds */ int32_t delay = OS_TICKS_PER_SEC * 3 ; os_time_delay ( delay );","title":"os_time_delay"},{"location":"os/core_os/time/os_time_delay/#os_time_delay","text":"void os_time_delay ( int32_t ticks )","title":"os_time_delay"},{"location":"os/core_os/time/os_time_delay/#arguments","text":"Arguments Description ticks Number of ticks to delay. Less than or equal to zero means no delay","title":"Arguments"},{"location":"os/core_os/time/os_time_delay/#returned-values","text":"N/A","title":"Returned values"},{"location":"os/core_os/time/os_time_delay/#notes","text":"Passing OS_TIMEOUT_NEVER to this function will not block indefinitely but will return immediately. Passing delays larger than 1/2 the OS time epoch should be avoided; behavior is unpredictable.","title":"Notes"},{"location":"os/core_os/time/os_time_delay/#example","text":"/* delay 3 seconds */ int32_t delay = OS_TICKS_PER_SEC * 3 ; os_time_delay ( delay );","title":"Example"},{"location":"os/core_os/time/os_time_get/","text":"os_time_get os_time_t os_time_get ( void ) Arguments N/A Returned values The current value of the OS time Notes See the Special Notes on OS time epoch and comparison Example os_time_t now = os_time_get ();","title":"os_time_get"},{"location":"os/core_os/time/os_time_get/#os_time_get","text":"os_time_t os_time_get ( void )","title":"os_time_get"},{"location":"os/core_os/time/os_time_get/#arguments","text":"N/A","title":"Arguments"},{"location":"os/core_os/time/os_time_get/#returned-values","text":"The current value of the OS time","title":"Returned values"},{"location":"os/core_os/time/os_time_get/#notes","text":"See the Special Notes on OS time epoch and comparison","title":"Notes"},{"location":"os/core_os/time/os_time_get/#example","text":"os_time_t now = os_time_get ();","title":"Example"},{"location":"os/core_os/time/os_time_ms_to_ticks/","text":"os_time_ms_to_ticks int os_time_ms_to_ticks ( uint32_t ms , uint32_t *out_ticks ) Converts milliseconds to OS ticks. Arguments Arguments Description ms Number of milliseconds to convert to OS ticks. out_ticks Pointer to an uint32_t to return the number of OS ticks for ms milliseconds. N/A Returned values 0 : Success OS_EINVAL : Number of ticks is too large to fit in an uint32_t. N/A Notes Example unint32_t num_ticks ; os_time_ms_to_ticks ( 50 , &num_ticks );","title":"os_time_ms_to_ticks"},{"location":"os/core_os/time/os_time_ms_to_ticks/#os_time_ms_to_ticks","text":"int os_time_ms_to_ticks ( uint32_t ms , uint32_t *out_ticks ) Converts milliseconds to OS ticks.","title":"os_time_ms_to_ticks"},{"location":"os/core_os/time/os_time_ms_to_ticks/#arguments","text":"Arguments Description ms Number of milliseconds to convert to OS ticks. out_ticks Pointer to an uint32_t to return the number of OS ticks for ms milliseconds. N/A","title":"Arguments"},{"location":"os/core_os/time/os_time_ms_to_ticks/#returned-values","text":"0 : Success OS_EINVAL : Number of ticks is too large to fit in an uint32_t. N/A","title":"Returned values"},{"location":"os/core_os/time/os_time_ms_to_ticks/#notes","text":"","title":"Notes"},{"location":"os/core_os/time/os_time_ms_to_ticks/#example","text":"unint32_t num_ticks ; os_time_ms_to_ticks ( 50 , &num_ticks );","title":"Example"},{"location":"os/get_started/cross_tools/","text":"Installing the Cross Tools for ARM This page shows you how to install the tools to build, run, and debug Mynewt OS applications that run on supported ARM target boards. It shows you how to install the following tools on Mac OS, Linux and Windows: ARM cross toolchain to compile and build Mynewt applications for the target boards. Debuggers to load and debug applications on the target boards. Installing the ARM Cross Toolchain ARM maintains a pre-built GNU toolchain with gcc and gdb targeted at Embedded ARM Processors, namely Cortex-R/Cortex-M processor families. Mynewt OS has been tested with version 4.9 of the toolchain and we recommend you install this version to get started. Mynewt OS will eventually work with multiple versions available, including the latest releases. Installing the ARM Toolchain For Mac OS X Add the PX4/homebrew-px4 homebrew tap and install version 4.9 of the toolchain. After installing, check that the symbolic link that homebrew created points to the correct version of the debugger. $ brew tap PX4/homebrew-px4 $ brew update $ brew install gcc-arm-none-eabi-49 $ arm-none-eabi-gcc --version arm-none-eabi-gcc (GNU Tools for ARM Embedded Processors) 4.9.3 20150529 (release) [ARM/embedded-4_9-branch revision 224288] Copyright (C) 2014 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. $ ls -al /usr/local/bin/arm-none-eabi-gdb lrwxr-xr-x 1 aditihilbert admin 69 Sep 22 17:16 /usr/local/bin/arm-none-eabi-gdb -> /usr/local/Cellar/gcc-arm-none-eabi-49/20150609/bin/arm-none-eabi-gdb Note: If no version is specified, brew will install the latest version available. Installing the ARM Toolchain For Linux On a Debian-based Linux distribution, gcc 4.9.3 for ARM can be installed with apt-get as documented below. The steps are explained in depth at https://launchpad.net/~team-gcc-arm-embedded/+archive/ubuntu/ppa . $ sudo apt-get remove binutils-arm-none-eabi gcc-arm-none-eabi $ sudo add-apt-repository ppa:team-gcc-arm-embedded/ppa $ sudo apt-get update $ sudo apt-get install gcc-arm-none-eabi $ sudo apt-get install gdb-arm-none-eabi Installing the ARM Toolchain for Windows Step 1: Download and run the installer to install arm-none-eabi-gcc and arm-none-eabi-gdb. Select the default destination folder: C:\\Program Files (x86)\\GNU Tools ARM Embedded\\4.9 2015q2 . Note: You may select a different folder but the installation instructions use the default values. Step 2: Add the path: C:\\Program Files (x86)\\GNU Tools ARM Embedded\\4.9 2015q2\\bin to your Windows Path environment variable. Note: You must add bin to the path. Step 3: Check that you are using the installed versions arm-none-eabi-gcc and arm-none-eabi-gdb. Open a MinGW terminal and run the which commands. Note: You must start a new MinGW terminal to inherit the new Path values. $ which arm-none-eabi-gcc /c/Program Files (x86)/GNU Tools ARM Embedded/4.9 2015q2/bin/arm-none-eabi-gcc $which arm-none-eabi-gdb /c/Program Files (x86)/GNU Tools ARM Embedded/4.9 2015q2/bin/arm-none-eabi-gdb Installing the Debuggers Mynewt uses, depending on the board, either the OpenOCD or SEGGER J-Link debuggers. Installing the OpenOCD Debugger OpenOCD (Open On-Chip Debugger) is open-source software that allows your computer to interface with the JTAG debug connector on a variety of boards. A JTAG connection lets you debug and test embedded target devices. For more on OpenOCD go to http://openocd.org . OpenOCD version 0.10.0 with nrf52 support is required. A binary for this version is available to download for Mac OS, Linux, and Windows. Installing OpenOCD on Mac OS Step 1: Download the binary tarball for Mac OS . Step 2: Change to the root directory: $cd / Step 3: Untar the tarball and install into ** /usr/local/bin**. You will need to replace ** ~/Downloads ** with the directory that the tarball is downloaded to. sudo tar -xf ~/Downloads/openocd-bin-0.10.0-MacOS.tgz ` Step 4: Check the OpenOCD version you are using. $which openocd /usr/local/bin/openocd $openocd -v Open On-Chip Debugger 0.10.0 Licensed under GNU GPL v2 For bug reports, read http://openocd.org/doc/doxygen/bugs.html You should see version: 0.10.0 . Installing OpenOCD on Linux Step 1: Download the binary tarball for Linux Step 2: Change to the root directory: $cd / Step 3: Untar the tarball and install into ** /usr/local/bin**. You will need to replace ** ~/Downloads ** with the directory that the tarball is downloaded to. ** Note:** You must specify the -p option for the tar command. $sudo tar -xpf ~/Downloads/openocd-bin-0.10.0-Linux.tgz Step 4: Check the OpenOCD version you are using: $which openocd /usr/local/bin/openocd $openocd -v Open On-Chip Debugger 0.10.0 Licensed under GNU GPL v2 For bug reports, read http://openocd.org/doc/doxygen/bugs.html You should see version: 0.10.0 . If you see any of these error messages: openocd: error while loading shared libraries: libhidapi-hidraw.so.0: cannot open shared object file: No such file or directory openocd: error while loading shared libraries: libusb-1.0.so.0: cannot open shared object file: No such file or directory run the following command to install the libraries: $sudo apt-get install libhidapi-dev:i386 Installing OpenOCD on Windows Step 1: Download the binary zip file for Windows . Step 2: Extract into the C:\\openocd-0.10.0 folder. Step 3: Add the path: ** C:\\openocd-0.10.0\\bin to your Windows User Path environment variable. Note: You must add bin** to the path. Step 4: Check the OpenOCD version you are using. Open a new MinGW terminal and run the following commands: Note: You must start a new MinGW terminal to inherit the new Path values. $which openocd /c/openocd-0.10.0/bin/openocd $openocd -v Open On-Chip Debugger 0.10.0 Licensed under GNU GPL v2 For bug reports, read http://openocd.org/doc/doxygen/bugs.html You should see version: 0.10.0 . Installing SEGGAR J-Link You can download and install Segger J-LINK Software and documentation pack from SEGGER . Note: On Windows, perform the following after the installation: Add the installation destination folder path to your Windows user Path environment variable. You do not need to add bin to the path. Open a new MinGW terminal to inherit the new Path values.","title":"Install Cross Tools for ARM"},{"location":"os/get_started/cross_tools/#installing-the-cross-tools-for-arm","text":"This page shows you how to install the tools to build, run, and debug Mynewt OS applications that run on supported ARM target boards. It shows you how to install the following tools on Mac OS, Linux and Windows: ARM cross toolchain to compile and build Mynewt applications for the target boards. Debuggers to load and debug applications on the target boards.","title":"Installing the Cross Tools for ARM"},{"location":"os/get_started/cross_tools/#installing-the-arm-cross-toolchain","text":"ARM maintains a pre-built GNU toolchain with gcc and gdb targeted at Embedded ARM Processors, namely Cortex-R/Cortex-M processor families. Mynewt OS has been tested with version 4.9 of the toolchain and we recommend you install this version to get started. Mynewt OS will eventually work with multiple versions available, including the latest releases.","title":"Installing the ARM Cross Toolchain"},{"location":"os/get_started/cross_tools/#installing-the-arm-toolchain-for-mac-os-x","text":"Add the PX4/homebrew-px4 homebrew tap and install version 4.9 of the toolchain. After installing, check that the symbolic link that homebrew created points to the correct version of the debugger. $ brew tap PX4/homebrew-px4 $ brew update $ brew install gcc-arm-none-eabi-49 $ arm-none-eabi-gcc --version arm-none-eabi-gcc (GNU Tools for ARM Embedded Processors) 4.9.3 20150529 (release) [ARM/embedded-4_9-branch revision 224288] Copyright (C) 2014 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. $ ls -al /usr/local/bin/arm-none-eabi-gdb lrwxr-xr-x 1 aditihilbert admin 69 Sep 22 17:16 /usr/local/bin/arm-none-eabi-gdb -> /usr/local/Cellar/gcc-arm-none-eabi-49/20150609/bin/arm-none-eabi-gdb Note: If no version is specified, brew will install the latest version available.","title":"Installing the ARM Toolchain For Mac OS X"},{"location":"os/get_started/cross_tools/#installing-the-arm-toolchain-for-linux","text":"On a Debian-based Linux distribution, gcc 4.9.3 for ARM can be installed with apt-get as documented below. The steps are explained in depth at https://launchpad.net/~team-gcc-arm-embedded/+archive/ubuntu/ppa . $ sudo apt-get remove binutils-arm-none-eabi gcc-arm-none-eabi $ sudo add-apt-repository ppa:team-gcc-arm-embedded/ppa $ sudo apt-get update $ sudo apt-get install gcc-arm-none-eabi $ sudo apt-get install gdb-arm-none-eabi","title":"Installing the ARM Toolchain For Linux"},{"location":"os/get_started/cross_tools/#installing-the-arm-toolchain-for-windows","text":"Step 1: Download and run the installer to install arm-none-eabi-gcc and arm-none-eabi-gdb. Select the default destination folder: C:\\Program Files (x86)\\GNU Tools ARM Embedded\\4.9 2015q2 . Note: You may select a different folder but the installation instructions use the default values. Step 2: Add the path: C:\\Program Files (x86)\\GNU Tools ARM Embedded\\4.9 2015q2\\bin to your Windows Path environment variable. Note: You must add bin to the path. Step 3: Check that you are using the installed versions arm-none-eabi-gcc and arm-none-eabi-gdb. Open a MinGW terminal and run the which commands. Note: You must start a new MinGW terminal to inherit the new Path values. $ which arm-none-eabi-gcc /c/Program Files (x86)/GNU Tools ARM Embedded/4.9 2015q2/bin/arm-none-eabi-gcc $which arm-none-eabi-gdb /c/Program Files (x86)/GNU Tools ARM Embedded/4.9 2015q2/bin/arm-none-eabi-gdb","title":"Installing the ARM Toolchain for Windows"},{"location":"os/get_started/cross_tools/#installing-the-debuggers","text":"Mynewt uses, depending on the board, either the OpenOCD or SEGGER J-Link debuggers.","title":"Installing the Debuggers"},{"location":"os/get_started/cross_tools/#installing-the-openocd-debugger","text":"OpenOCD (Open On-Chip Debugger) is open-source software that allows your computer to interface with the JTAG debug connector on a variety of boards. A JTAG connection lets you debug and test embedded target devices. For more on OpenOCD go to http://openocd.org . OpenOCD version 0.10.0 with nrf52 support is required. A binary for this version is available to download for Mac OS, Linux, and Windows.","title":"Installing the OpenOCD Debugger"},{"location":"os/get_started/cross_tools/#installing-openocd-on-mac-os","text":"Step 1: Download the binary tarball for Mac OS . Step 2: Change to the root directory: $cd / Step 3: Untar the tarball and install into ** /usr/local/bin**. You will need to replace ** ~/Downloads ** with the directory that the tarball is downloaded to. sudo tar -xf ~/Downloads/openocd-bin-0.10.0-MacOS.tgz ` Step 4: Check the OpenOCD version you are using. $which openocd /usr/local/bin/openocd $openocd -v Open On-Chip Debugger 0.10.0 Licensed under GNU GPL v2 For bug reports, read http://openocd.org/doc/doxygen/bugs.html You should see version: 0.10.0 .","title":"Installing OpenOCD on Mac OS"},{"location":"os/get_started/cross_tools/#installing-openocd-on-linux","text":"Step 1: Download the binary tarball for Linux Step 2: Change to the root directory: $cd / Step 3: Untar the tarball and install into ** /usr/local/bin**. You will need to replace ** ~/Downloads ** with the directory that the tarball is downloaded to. ** Note:** You must specify the -p option for the tar command. $sudo tar -xpf ~/Downloads/openocd-bin-0.10.0-Linux.tgz Step 4: Check the OpenOCD version you are using: $which openocd /usr/local/bin/openocd $openocd -v Open On-Chip Debugger 0.10.0 Licensed under GNU GPL v2 For bug reports, read http://openocd.org/doc/doxygen/bugs.html You should see version: 0.10.0 . If you see any of these error messages: openocd: error while loading shared libraries: libhidapi-hidraw.so.0: cannot open shared object file: No such file or directory openocd: error while loading shared libraries: libusb-1.0.so.0: cannot open shared object file: No such file or directory run the following command to install the libraries: $sudo apt-get install libhidapi-dev:i386","title":"Installing OpenOCD on Linux"},{"location":"os/get_started/cross_tools/#installing-openocd-on-windows","text":"Step 1: Download the binary zip file for Windows . Step 2: Extract into the C:\\openocd-0.10.0 folder. Step 3: Add the path: ** C:\\openocd-0.10.0\\bin to your Windows User Path environment variable. Note: You must add bin** to the path. Step 4: Check the OpenOCD version you are using. Open a new MinGW terminal and run the following commands: Note: You must start a new MinGW terminal to inherit the new Path values. $which openocd /c/openocd-0.10.0/bin/openocd $openocd -v Open On-Chip Debugger 0.10.0 Licensed under GNU GPL v2 For bug reports, read http://openocd.org/doc/doxygen/bugs.html You should see version: 0.10.0 .","title":"Installing OpenOCD on Windows"},{"location":"os/get_started/cross_tools/#installing-seggar-j-link","text":"You can download and install Segger J-LINK Software and documentation pack from SEGGER . Note: On Windows, perform the following after the installation: Add the installation destination folder path to your Windows user Path environment variable. You do not need to add bin to the path. Open a new MinGW terminal to inherit the new Path values.","title":"Installing SEGGAR J-Link"},{"location":"os/get_started/docker/","text":"Everything You Need in a Docker Container Docker provides a quick and easy way to get up and running with Mynewt. The newt command line tool and the entire build toolchain is available in a single docker container. The container is all that's needed to run your Mynewt based application in the simulator. Enabling USB2 with your docker installation will allow you to load your application on a supported device. Docker is the only supported option if you are working on a Windows machine. If you are using Mac OS X or Linux, you have the choice of installing a Docker container of tools and toolchains or installing them natively. This chapter describes how to set up the Docker image for all three platforms. Install Docker Install docker for your platform. Mac OS X / Windows / Linux Mac and Windows Mac and Windows require Docker Toolbox to interact with USB devices. Docker for Mac and Docker for Windows do not support USB. Docker Toolbox uses VirtualBox and allows you to map USB devices into docker containers as described below. Make sure to double click the Docker Quickstart Terminal application if you're on Mac or Windows. Linux The docker daemon listens on a Unix domain socket on Linux. That socket is owned by root, which means by default you must be root to start a container. Make sure to follow the optional step of adding yourself to the docker group so you can start the newt container as yourself. Use the newt wrapper script Use the newt wrapper script to invoke newt. Create the following file, name it newt , make it executable, and put it in your path. This will allow you to run newt as if it was natively installed. You can now follow the normal tutorials using the newt wrapper script. #!/bin/bash if [ \" $1 \" = \"debug\" ] || [ \" $1 \" = \"run\" ] then ti= \"-ti\" fi docker run -e NEWT_USER= $( id -u ) -e NEWT_GROUP= $( id -g ) -e NEWT_HOST= $( uname ) $ti --rm --device = /dev/bus/usb --privileged -v $(pwd) :/workspace -w /workspace mynewt/newt:latest /newt \" $@ \" Note 1: Remember to point to the correct subdirectory level when invoking newt . For example, invoke it using ../newt in the example below. user@~/dockertest$ ls myproj newt user@~/dockertest$ cd myproj user@~/dockertest/myproj$ ../newt version Apache Newt (incubating) version: 0.8.0-b2 Note 2: You can upgrade your container by running docker pull mynewt/newt:latest when updates are made available. Enable USB2 Support for Mac or Windows If you plan on loading your application on an actual device, do the steps below. Install VirtualBox extension pack Docker uses a VirtualBox Linux VM to run containers. A free VirtualBox extension pack is required to enable USB2 support. Download the VirtualBox 5.0.16 Oracle VM VirtualBox Extension Pack and double click to install Enable USB2 and select your device The \"default\" VM created by docker-machine must first be stopped before you can enable USB2. You have two options: Run the command docker-machine stop default in the terminal window or Use the VirtualBox UI. Right click on default -> Close -> Power Off Enable USB2 using the VirtualBox UI. Select the \"default\" VM->Settings->Ports->USB2 to enable USB2. Add your device to the USB Device Filters to make the device visible in the docker container. See the image below. Restart the \"default\" VM. You have two options: Run docker-machine start default in the terminal window or Use the VirtualBox UI. Make sure the \"default\" machine is highlighted. Click the green \"Start\" button. Select \"Headless Start\". Note 3 : When working with actual hardware, remember that each board has an ID. If you swap boards and do not refresh the USB Device Filter on the VirtualBox UI, the ID might be stale and the Docker instance may not be able to see the board correctly. For example, you may see an error message like Error: unable to find CMSIS-DAP device when you try to load or run an image on the board. In that case, you need to click on the USB link in VirtualBox UI, remove the existing USB Device Filter (e.g. \"Atmel Corp. EDBG CMSIS-DAP[0101]\") by clicking on the \"Removes selected USB filter\" button, and add a new filter by clicking on the \"Adds new USB filter\" button.","title":"Docker Container Option"},{"location":"os/get_started/docker/#everything-you-need-in-a-docker-container","text":"Docker provides a quick and easy way to get up and running with Mynewt. The newt command line tool and the entire build toolchain is available in a single docker container. The container is all that's needed to run your Mynewt based application in the simulator. Enabling USB2 with your docker installation will allow you to load your application on a supported device. Docker is the only supported option if you are working on a Windows machine. If you are using Mac OS X or Linux, you have the choice of installing a Docker container of tools and toolchains or installing them natively. This chapter describes how to set up the Docker image for all three platforms.","title":"Everything You Need in a Docker Container"},{"location":"os/get_started/docker/#install-docker","text":"Install docker for your platform. Mac OS X / Windows / Linux","title":"Install Docker"},{"location":"os/get_started/docker/#mac-and-windows","text":"Mac and Windows require Docker Toolbox to interact with USB devices. Docker for Mac and Docker for Windows do not support USB. Docker Toolbox uses VirtualBox and allows you to map USB devices into docker containers as described below. Make sure to double click the Docker Quickstart Terminal application if you're on Mac or Windows.","title":"Mac and Windows"},{"location":"os/get_started/docker/#linux","text":"The docker daemon listens on a Unix domain socket on Linux. That socket is owned by root, which means by default you must be root to start a container. Make sure to follow the optional step of adding yourself to the docker group so you can start the newt container as yourself.","title":"Linux"},{"location":"os/get_started/docker/#use-the-newt-wrapper-script","text":"Use the newt wrapper script to invoke newt. Create the following file, name it newt , make it executable, and put it in your path. This will allow you to run newt as if it was natively installed. You can now follow the normal tutorials using the newt wrapper script. #!/bin/bash if [ \" $1 \" = \"debug\" ] || [ \" $1 \" = \"run\" ] then ti= \"-ti\" fi docker run -e NEWT_USER= $( id -u ) -e NEWT_GROUP= $( id -g ) -e NEWT_HOST= $( uname ) $ti --rm --device = /dev/bus/usb --privileged -v $(pwd) :/workspace -w /workspace mynewt/newt:latest /newt \" $@ \" Note 1: Remember to point to the correct subdirectory level when invoking newt . For example, invoke it using ../newt in the example below. user@~/dockertest$ ls myproj newt user@~/dockertest$ cd myproj user@~/dockertest/myproj$ ../newt version Apache Newt (incubating) version: 0.8.0-b2 Note 2: You can upgrade your container by running docker pull mynewt/newt:latest when updates are made available.","title":"Use the newt wrapper script"},{"location":"os/get_started/docker/#enable-usb2-support-for-mac-or-windows","text":"If you plan on loading your application on an actual device, do the steps below.","title":"Enable USB2 Support for Mac or Windows"},{"location":"os/get_started/docker/#install-virtualbox-extension-pack","text":"Docker uses a VirtualBox Linux VM to run containers. A free VirtualBox extension pack is required to enable USB2 support. Download the VirtualBox 5.0.16 Oracle VM VirtualBox Extension Pack and double click to install","title":"Install VirtualBox extension pack"},{"location":"os/get_started/docker/#enable-usb2-and-select-your-device","text":"The \"default\" VM created by docker-machine must first be stopped before you can enable USB2. You have two options: Run the command docker-machine stop default in the terminal window or Use the VirtualBox UI. Right click on default -> Close -> Power Off Enable USB2 using the VirtualBox UI. Select the \"default\" VM->Settings->Ports->USB2 to enable USB2. Add your device to the USB Device Filters to make the device visible in the docker container. See the image below. Restart the \"default\" VM. You have two options: Run docker-machine start default in the terminal window or Use the VirtualBox UI. Make sure the \"default\" machine is highlighted. Click the green \"Start\" button. Select \"Headless Start\". Note 3 : When working with actual hardware, remember that each board has an ID. If you swap boards and do not refresh the USB Device Filter on the VirtualBox UI, the ID might be stale and the Docker instance may not be able to see the board correctly. For example, you may see an error message like Error: unable to find CMSIS-DAP device when you try to load or run an image on the board. In that case, you need to click on the USB link in VirtualBox UI, remove the existing USB Device Filter (e.g. \"Atmel Corp. EDBG CMSIS-DAP[0101]\") by clicking on the \"Removes selected USB filter\" button, and add a new filter by clicking on the \"Adds new USB filter\" button.","title":"Enable USB2 and select your device"},{"location":"os/get_started/get_started/","text":"Quick Start If you are curious about Mynewt and want to get a quick feel for the project, you've come to the right place. We have two options for you: Option 1 (Recommended) allows you to install the Newt tool, instances of the Mynewt OS (for simulated targets), and toolchains for developing embedded software (e.g. GNU toolchain) natively on your laptop or computer. We have tried to make the process easy. For example, for the Mac OS we created brew formulas. We recommend this option if you are familiar with such environments or are concerned about performance on your machine. Follow the instructions in the Native Install Option if you prefer this option. Option 2 is an easy, self-contained way to get up and running with Mynewt - but has limitations! The Newt tool and build toolchains are all available in a single All-in-one Docker Container that you can install on your laptop or computer. However, this is not a long-term option since support is not likely for all features useful or critical to embedded systems development. For example, USB device mapping available in the Docker toolkit is no longer available in the new Docker releases. The Docker option is also typically slower than the native install option. You can then proceed with the instructions on how to * Create Your First Project - on simulated hardware. Upon successful start, several tutorials await your eager attention! Send us an email on the dev@ mailing list if you have comments or suggestions! If you haven't joined the mailing list, you will find the links here .","title":"toc"},{"location":"os/get_started/get_started/#quick-start","text":"If you are curious about Mynewt and want to get a quick feel for the project, you've come to the right place. We have two options for you: Option 1 (Recommended) allows you to install the Newt tool, instances of the Mynewt OS (for simulated targets), and toolchains for developing embedded software (e.g. GNU toolchain) natively on your laptop or computer. We have tried to make the process easy. For example, for the Mac OS we created brew formulas. We recommend this option if you are familiar with such environments or are concerned about performance on your machine. Follow the instructions in the Native Install Option if you prefer this option. Option 2 is an easy, self-contained way to get up and running with Mynewt - but has limitations! The Newt tool and build toolchains are all available in a single All-in-one Docker Container that you can install on your laptop or computer. However, this is not a long-term option since support is not likely for all features useful or critical to embedded systems development. For example, USB device mapping available in the Docker toolkit is no longer available in the new Docker releases. The Docker option is also typically slower than the native install option. You can then proceed with the instructions on how to * Create Your First Project - on simulated hardware. Upon successful start, several tutorials await your eager attention! Send us an email on the dev@ mailing list if you have comments or suggestions! If you haven't joined the mailing list, you will find the links here .","title":"Quick Start"},{"location":"os/get_started/native_install_intro/","text":"Native Installation This section shows you how to install the tools to develop and build Mynewt OS applications on Mac OS, Linux, and Windows, and run and debug the applications on target boards. For Mac OS and Linux, you can also build Mynewt OS applications that run on Mynewt's simulated hardware. These applications run natively on Mac OS and Linux. The tools you need are: Newt tool: Tool to create, build, load, and debug Mynewt OS applications. See Installing the Newt Tool on Mac OS to install on Mac OS. See Installing the Newt Tool on Linux to install on Linux. See Installing the Newt Tool on Windows to install on Windows. Native toolchain: Native toolchain to compile and build Mynewt OS applications that run on Mynewt's simulated hardware on Mac OS and Linux. (See Installing Native Toolchain ). Cross tools for ARM: Cross toolchain for ARM to compile and build Mynewt OS applications for target boards. Debuggers to load and debug applications on target boards. (See Installing Cross Tools for ARMs ). If you would like to use an IDE to develop and debug Mynewt applications, see using an IDE to develop Mynewt Applications . You must still perform the native installation outlined on this page.","title":"toc"},{"location":"os/get_started/native_install_intro/#native-installation","text":"This section shows you how to install the tools to develop and build Mynewt OS applications on Mac OS, Linux, and Windows, and run and debug the applications on target boards. For Mac OS and Linux, you can also build Mynewt OS applications that run on Mynewt's simulated hardware. These applications run natively on Mac OS and Linux. The tools you need are: Newt tool: Tool to create, build, load, and debug Mynewt OS applications. See Installing the Newt Tool on Mac OS to install on Mac OS. See Installing the Newt Tool on Linux to install on Linux. See Installing the Newt Tool on Windows to install on Windows. Native toolchain: Native toolchain to compile and build Mynewt OS applications that run on Mynewt's simulated hardware on Mac OS and Linux. (See Installing Native Toolchain ). Cross tools for ARM: Cross toolchain for ARM to compile and build Mynewt OS applications for target boards. Debuggers to load and debug applications on target boards. (See Installing Cross Tools for ARMs ). If you would like to use an IDE to develop and debug Mynewt applications, see using an IDE to develop Mynewt Applications . You must still perform the native installation outlined on this page.","title":"Native Installation"},{"location":"os/get_started/native_tools/","text":"Installing Native Toolchain This page shows you how to install the toolchain to build Mynewt OS applications that run native on Mac OS and Linux. The applications run on Mynewt's simulated hardware. It also allows you to run the test suites for all packages that do not require HW support. Note: This is not supported on Windows. Setting Up the Toolchain for Mac Installing Brew If you have not already installed Homebrew from the newt tutorials pages , install it. Installing gcc/libc OS X ships with a C compiler called Clang. To build applications for the Mynewt simulator with, a different compiler is used as default: gcc. $ brew install gcc ... ... ==> Summary \ud83c\udf7a /usr/local/Cellar/gcc/5.2.0: 1353 files, 248M Check the gcc version you have installed (either using brew or previously installed). The brew-installed version can be checked using brew list gcc . The default compiler.yml configuration file in Mynewt expects version 5.x for Mac users, so if the installed version is 6.x and you wish to continue with this newer version, modify the <mynewt-src-directory>/repos/apache-mynewt-core/compiler/sim/compiler.yml file to change the default gcc-5 defined there to gcc-6 . In other words, replace the lines shown highlighted below: # OS X. compiler.path.cc.DARWIN.OVERWRITE: \"gcc-5\" compiler.path.as.DARWIN.OVERWRITE: \"gcc-5\" compiler.path.objdump.DARWIN.OVERWRITE: \"gobjdump\" compiler.path.objsize.DARWIN.OVERWRITE: \"objsize\" compiler.path.objcopy.DARWIN.OVERWRITE: \"gobjcopy\" with the following: compiler.path.cc.DARWIN.OVERWRITE: \"gcc-6\" compiler.path.as.DARWIN.OVERWRITE: \"gcc-6\u201d In case you wish to use Clang, you can change your <mynewt-src-directory>/repos/apache-mynewt-core/compiler/sim/compiler.yml to use Clang. Delete the gcc-5 DARWIN.OVERWRITE lines highlighted below. # OS X. compiler.path.cc.DARWIN.OVERWRITE: \"gcc-5\" compiler.path.as.DARWIN.OVERWRITE: \"gcc-5\" compiler.path.objdump.DARWIN.OVERWRITE: \"gobjdump\" compiler.path.objsize.DARWIN.OVERWRITE: \"objsize\" compiler.path.objcopy.DARWIN.OVERWRITE: \"gobjcopy\" NOTE: Both the newer gcc 6.x and Clang report a few warnings but they can be ignored. FURTHER NOTE: Mynewt developers mostly use gcc 5.x for sim builds; so it may take a little while to fix issues reported by the newer compiler. One option is to disable warnings . To do that, remove the -Werror flag as an option for the compiler in the <mynewt-src-directory>/repos/apache-mynewt-core/compiler/sim/compiler.yml file as shown below. compiler.flags.base: > -m32 -Wall -ggdb You may alternatively choose to specify the precise warnings to ignore depending on the error thrown by the compiler. For example, if you see a [-Werror=misleading-indentation] error while building the sim image, add -Wno-misleading-indentation] as a compiler flag in the same line from the <mynewt-src-directory>/repos/apache-mynewt-core/compiler/sim/compiler.yml file. compiler.flags.base: > -m32 -Wall -Werror -ggdb -Wno-misleading-indentation A third option is to simply downgrade to gcc 5.x . Installing gdb $ brew install gdb ... ... ==> Summary \ud83c\udf7a /usr/local/Cellar/gdb/7.10.1: XXX files,YYM NOTE: When running a program with gdb, you may need to sign your gdb executable. This page shows a recipe for gdb signing. Alternately you can skip this step and continue without the ability to debug your mynewt application on your PC.* Setting Up the Toolchain for Linux The below procedure can be used to set up a Debian-based Linux system (e.g., Ubuntu). If you are running a different Linux distribution, you will need to substitute invocations of apt-get in the below steps with the package manager that your distro uses. Install gcc/libc that will produce 32-bit executables: $ sudo apt-get install gcc-multilib libc6-i386 Install gdb $ sudo apt-get install gdb Reading package lists... Done Building dependency tree Reading state information... Done Suggested packages: gdb-doc gdbserver The following NEW packages will be installed: gdb ... Processing triggers for man-db (2.6.7.1-1ubuntu1) ... Setting up gdb (7.7.1-0ubuntu5~14.04.2) ... At this point you have installed all the necessary software to build and run your first project on a simluator on your Mac OS or Linux computer. You may proceed to the Create Your First Project section or continue to the next section and install the cross tools for ARM.","title":"Install Native Toolchain"},{"location":"os/get_started/native_tools/#installing-native-toolchain","text":"This page shows you how to install the toolchain to build Mynewt OS applications that run native on Mac OS and Linux. The applications run on Mynewt's simulated hardware. It also allows you to run the test suites for all packages that do not require HW support. Note: This is not supported on Windows.","title":"Installing Native Toolchain"},{"location":"os/get_started/native_tools/#setting-up-the-toolchain-for-mac","text":"","title":"Setting Up the Toolchain for Mac"},{"location":"os/get_started/native_tools/#installing-brew","text":"If you have not already installed Homebrew from the newt tutorials pages , install it.","title":"Installing Brew"},{"location":"os/get_started/native_tools/#installing-gcclibc","text":"OS X ships with a C compiler called Clang. To build applications for the Mynewt simulator with, a different compiler is used as default: gcc. $ brew install gcc ... ... ==> Summary \ud83c\udf7a /usr/local/Cellar/gcc/5.2.0: 1353 files, 248M Check the gcc version you have installed (either using brew or previously installed). The brew-installed version can be checked using brew list gcc . The default compiler.yml configuration file in Mynewt expects version 5.x for Mac users, so if the installed version is 6.x and you wish to continue with this newer version, modify the <mynewt-src-directory>/repos/apache-mynewt-core/compiler/sim/compiler.yml file to change the default gcc-5 defined there to gcc-6 . In other words, replace the lines shown highlighted below: # OS X. compiler.path.cc.DARWIN.OVERWRITE: \"gcc-5\" compiler.path.as.DARWIN.OVERWRITE: \"gcc-5\" compiler.path.objdump.DARWIN.OVERWRITE: \"gobjdump\" compiler.path.objsize.DARWIN.OVERWRITE: \"objsize\" compiler.path.objcopy.DARWIN.OVERWRITE: \"gobjcopy\" with the following: compiler.path.cc.DARWIN.OVERWRITE: \"gcc-6\" compiler.path.as.DARWIN.OVERWRITE: \"gcc-6\u201d In case you wish to use Clang, you can change your <mynewt-src-directory>/repos/apache-mynewt-core/compiler/sim/compiler.yml to use Clang. Delete the gcc-5 DARWIN.OVERWRITE lines highlighted below. # OS X. compiler.path.cc.DARWIN.OVERWRITE: \"gcc-5\" compiler.path.as.DARWIN.OVERWRITE: \"gcc-5\" compiler.path.objdump.DARWIN.OVERWRITE: \"gobjdump\" compiler.path.objsize.DARWIN.OVERWRITE: \"objsize\" compiler.path.objcopy.DARWIN.OVERWRITE: \"gobjcopy\" NOTE: Both the newer gcc 6.x and Clang report a few warnings but they can be ignored. FURTHER NOTE: Mynewt developers mostly use gcc 5.x for sim builds; so it may take a little while to fix issues reported by the newer compiler. One option is to disable warnings . To do that, remove the -Werror flag as an option for the compiler in the <mynewt-src-directory>/repos/apache-mynewt-core/compiler/sim/compiler.yml file as shown below. compiler.flags.base: > -m32 -Wall -ggdb You may alternatively choose to specify the precise warnings to ignore depending on the error thrown by the compiler. For example, if you see a [-Werror=misleading-indentation] error while building the sim image, add -Wno-misleading-indentation] as a compiler flag in the same line from the <mynewt-src-directory>/repos/apache-mynewt-core/compiler/sim/compiler.yml file. compiler.flags.base: > -m32 -Wall -Werror -ggdb -Wno-misleading-indentation A third option is to simply downgrade to gcc 5.x .","title":"Installing gcc/libc"},{"location":"os/get_started/native_tools/#installing-gdb","text":"$ brew install gdb ... ... ==> Summary \ud83c\udf7a /usr/local/Cellar/gdb/7.10.1: XXX files,YYM NOTE: When running a program with gdb, you may need to sign your gdb executable. This page shows a recipe for gdb signing. Alternately you can skip this step and continue without the ability to debug your mynewt application on your PC.*","title":"Installing gdb"},{"location":"os/get_started/native_tools/#setting-up-the-toolchain-for-linux","text":"The below procedure can be used to set up a Debian-based Linux system (e.g., Ubuntu). If you are running a different Linux distribution, you will need to substitute invocations of apt-get in the below steps with the package manager that your distro uses.","title":"Setting Up the Toolchain for Linux"},{"location":"os/get_started/native_tools/#install-gcclibc-that-will-produce-32-bit-executables","text":"$ sudo apt-get install gcc-multilib libc6-i386","title":"Install gcc/libc that will produce 32-bit executables:"},{"location":"os/get_started/native_tools/#install-gdb","text":"$ sudo apt-get install gdb Reading package lists... Done Building dependency tree Reading state information... Done Suggested packages: gdb-doc gdbserver The following NEW packages will be installed: gdb ... Processing triggers for man-db (2.6.7.1-1ubuntu1) ... Setting up gdb (7.7.1-0ubuntu5~14.04.2) ... At this point you have installed all the necessary software to build and run your first project on a simluator on your Mac OS or Linux computer. You may proceed to the Create Your First Project section or continue to the next section and install the cross tools for ARM.","title":"Install gdb"},{"location":"os/get_started/project_create/","text":"Creating Your First Mynewt Project This page shows you how to create a Mynewt project using the newt command-line tool. The project is a blinky application that toggles a pin. The application uses the Mynewt's simulated hardware and runs as a native application on Mac OS and Linux. Note: The Mynewt simulator is not yet supported on Windows. If you are using the native install option (not the Docker option), you will need to create the blinky application for a target board. We recommend that you read the section on creating a new project and fetching the source repository to understand the Mynewt repository structure, create a new project, and fetch the source dependencies before proceeding to one of the Blinky Tutorials . This guide shows you how to: Create a new project and fetch the source repository and dependecies. Test the project packages (Not supported on Windows). Build and run the simulated blinky application (Not supported on Windows). Prerequisites Have Internet connectivity to fetch remote Mynewt components. Install the newt tool: If you have taken the native install option, see the installation instructions for Mac OS , Linux , or Windows . If you have taken the Docker option, you have already installed Newt. Install the native toolchain to compile and build a Mynewt native application. Creating a New Project and Fetching the Source Repository This section describes how to use the newt tool to create a new project and fetch the core mynewt source repository. Creating a New Project Choose a name for your project. We name the project myproj . Run the newt new myproj command, from your dev directory, to create a new project: Note: This tutorial assumes you created a dev directory under your home directory. $cd ~/dev $ newt new myproj Downloading project skeleton from apache/incubator-mynewt-blinky... Installing skeleton in myproj... Project myproj successfully created. The newt tool creates a project base directory name myproj . All newt tool commands are run from the project base directory. The newt tool populates this new project with a base skeleton of a new Apache Mynewt project in the project base directory. It has the following structure: Note : If you do not have tree , run brew install tree to install on Mac OS, sudo apt-get install tree to install on Linux, and pacman -Su tree from a MinGW terminal to install on Windows. $ cd myproj $ tree . \u251c\u2500\u2500 DISCLAIMER \u251c\u2500\u2500 LICENSE \u251c\u2500\u2500 NOTICE \u251c\u2500\u2500 README.md \u251c\u2500\u2500 apps \u2502 \u2514\u2500\u2500 blinky \u2502 \u251c\u2500\u2500 pkg.yml \u2502 \u2514\u2500\u2500 src \u2502 \u2514\u2500\u2500 main.c \u251c\u2500\u2500 project.yml \u2514\u2500\u2500 targets \u251c\u2500\u2500 my_blinky_sim \u2502 \u251c\u2500\u2500 pkg.yml \u2502 \u2514\u2500\u2500 target.yml \u2514\u2500\u2500 unittest \u251c\u2500\u2500 pkg.yml \u2514\u2500\u2500 target.yml 6 directories, 11 files The newt tool installs the following files for a project in the project base directory: The file project.yml contains the repository list that the project uses to fetch its packages. Your project is a collection of repositories. In this case, the project only comprises the core mynewt repository. Later, you will add more repositories to include other mynewt components. The file apps/blinky/pkg.yml contains the description of your application and its package dependencies. A target directory that contains the my_blinky_sim directory. The my_blinky_sim directory a target information to build a version of myproj. Use newt target show to see available build targets. A non-buildable target called unittest . This is used internally by newt and is not a formal build target. Note: The actual code and package files are not installed (except the template for main.c ). See the next step to install the packages. Fetching the Mynewt Source Repository and Dependencies By default, Mynewt projects rely on a single repository: apache-mynewt-core and uses the source in the master branch. If you need to use a different branch, you need to change the vers value in the project.yml file: repository.apache-mynewt-core: type: github vers: 1-latest user: apache repo: incubator-mynewt-core Changing vers to 0-dev will put you on the latest master branch. This branch may not be stable and you may encounter bugs or other problems. Note: On Windows platforms, you will need to change vers to 0-dev and use the latest master branch. Release 1.0.0 is not supported on Windows. Run the newt install command, from your project base directory (myproj), to fetch the source repository and dependencies: $ newt install apache-mynewt-core Note: It may take a while to download the apache-mynewt-core reposistory. Use the -v (verbose) option to see the installation progress. View the core of the Apache Mynewt OS that is downloaded into your local directory. (The actual output will depend on what is in the latest 'master' branch) $ tree -L 2 repos/apache-mynewt-core/ repos/apache-mynewt-core/ \u251c\u2500\u2500 CODING_STANDARDS.md \u251c\u2500\u2500 DISCLAIMER \u251c\u2500\u2500 LICENSE \u251c\u2500\u2500 NOTICE \u251c\u2500\u2500 README.md \u251c\u2500\u2500 RELEASE_NOTES.md \u251c\u2500\u2500 apps \u2502 \u251c\u2500\u2500 blecent \u2502 \u251c\u2500\u2500 blehci \u2502 \u251c\u2500\u2500 bleprph \u2502 \u251c\u2500\u2500 bleprph_oic \u2502 \u251c\u2500\u2500 blesplit \u2502 \u251c\u2500\u2500 bletest \u2502 \u251c\u2500\u2500 bletiny \u2502 \u251c\u2500\u2500 bleuart \u2502 \u251c\u2500\u2500 boot \u2502 \u251c\u2500\u2500 fat2native \u2502 \u251c\u2500\u2500 ffs2native \u2502 \u251c\u2500\u2500 ocf_sample \u2502 \u251c\u2500\u2500 slinky \u2502 \u251c\u2500\u2500 slinky_oic \u2502 \u251c\u2500\u2500 spitest \u2502 \u251c\u2500\u2500 splitty \u2502 \u251c\u2500\u2500 test \u2502 \u251c\u2500\u2500 testbench \u2502 \u2514\u2500\u2500 timtest \u251c\u2500\u2500 boot \u2502 \u251c\u2500\u2500 boot_serial \u2502 \u251c\u2500\u2500 bootutil \u2502 \u251c\u2500\u2500 split \u2502 \u2514\u2500\u2500 split_app \u251c\u2500\u2500 compiler \u2502 \u251c\u2500\u2500 arm-none-eabi-m0 \u2502 \u251c\u2500\u2500 arm-none-eabi-m4 \u2502 \u251c\u2500\u2500 gdbmacros \u2502 \u251c\u2500\u2500 mips \u2502 \u251c\u2500\u2500 sim \u2502 \u2514\u2500\u2500 sim-mips \u251c\u2500\u2500 crypto \u2502 \u251c\u2500\u2500 mbedtls \u2502 \u2514\u2500\u2500 tinycrypt \u251c\u2500\u2500 docs \u2502 \u2514\u2500\u2500 doxygen.xml \u251c\u2500\u2500 encoding \u2502 \u251c\u2500\u2500 base64 \u2502 \u251c\u2500\u2500 cborattr \u2502 \u251c\u2500\u2500 json \u2502 \u2514\u2500\u2500 tinycbor \u251c\u2500\u2500 fs \u2502 \u251c\u2500\u2500 disk \u2502 \u251c\u2500\u2500 fatfs \u2502 \u251c\u2500\u2500 fcb \u2502 \u251c\u2500\u2500 fs \u2502 \u2514\u2500\u2500 nffs \u251c\u2500\u2500 hw \u2502 \u251c\u2500\u2500 bsp \u2502 \u251c\u2500\u2500 cmsis-core \u2502 \u251c\u2500\u2500 drivers \u2502 \u251c\u2500\u2500 hal \u2502 \u251c\u2500\u2500 mcu \u2502 \u2514\u2500\u2500 scripts \u251c\u2500\u2500 kernel \u2502 \u2514\u2500\u2500 os \u251c\u2500\u2500 libc \u2502 \u2514\u2500\u2500 baselibc \u251c\u2500\u2500 mgmt \u2502 \u251c\u2500\u2500 imgmgr \u2502 \u251c\u2500\u2500 mgmt \u2502 \u251c\u2500\u2500 newtmgr \u2502 \u2514\u2500\u2500 oicmgr \u251c\u2500\u2500 net \u2502 \u251c\u2500\u2500 ip \u2502 \u251c\u2500\u2500 nimble \u2502 \u251c\u2500\u2500 oic \u2502 \u2514\u2500\u2500 wifi \u251c\u2500\u2500 project.yml \u251c\u2500\u2500 repository.yml \u251c\u2500\u2500 sys \u2502 \u251c\u2500\u2500 config \u2502 \u251c\u2500\u2500 console \u2502 \u251c\u2500\u2500 coredump \u2502 \u251c\u2500\u2500 defs \u2502 \u251c\u2500\u2500 flash_map \u2502 \u251c\u2500\u2500 id \u2502 \u251c\u2500\u2500 log \u2502 \u251c\u2500\u2500 mfg \u2502 \u251c\u2500\u2500 reboot \u2502 \u251c\u2500\u2500 shell \u2502 \u251c\u2500\u2500 stats \u2502 \u2514\u2500\u2500 sysinit \u251c\u2500\u2500 targets \u2502 \u2514\u2500\u2500 unittest \u251c\u2500\u2500 test \u2502 \u251c\u2500\u2500 crash_test \u2502 \u251c\u2500\u2500 flash_test \u2502 \u251c\u2500\u2500 runtest \u2502 \u2514\u2500\u2500 testutil \u251c\u2500\u2500 time \u2502 \u2514\u2500\u2500 datetime \u2514\u2500\u2500 util \u251c\u2500\u2500 cbmem \u251c\u2500\u2500 crc \u2514\u2500\u2500 mem 94 directories, 9 files Testing the Project Packages Note : This is not yet supported on Windows. You can use the newt tool to execute the unit tests in a package. For example, run the following command to test the sys/config package in the apache-mynewt-core repo: $ newt test @apache-mynewt-core/sys/config Testing package @apache-mynewt-core/sys/config/test-fcb Compiling bootutil_misc.c Compiling image_ec.c Compiling image_rsa.c Compiling image_validate.c ... Linking ~/dev/myproj/bin/targets/unittest/sys_config_test-fcb/app/sys/config/test-fcb/sys_config_test-fcb.elf Executing test: ~/dev/myproj/bin/targets/unittest/sys_config_test-fcb/app/sys/config/test-fcb/sys_config_test-fcb.elf Testing package @apache-mynewt-core/sys/config/test-nffs Compiling repos/apache-mynewt-core/encoding/base64/src/hex.c Compiling repos/apache-mynewt-core/fs/fs/src/fs_cli.c Compiling repos/apache-mynewt-core/fs/fs/src/fs_dirent.c Compiling repos/apache-mynewt-core/fs/fs/src/fs_mkdir.c Compiling repos/apache-mynewt-core/fs/fs/src/fs_mount.c Compiling repos/apache-mynewt-core/encoding/base64/src/base64.c Compiling repos/apache-mynewt-core/fs/fs/src/fs_file.c Compiling repos/apache-mynewt-core/fs/disk/src/disk.c Compiling repos/apache-mynewt-core/fs/fs/src/fs_nmgr.c Compiling repos/apache-mynewt-core/fs/fs/src/fsutil.c Compiling repos/apache-mynewt-core/fs/nffs/src/nffs.c ... Linking ~/dev/myproj/bin/targets/unittest/sys_config_test-nffs/app/sys/config/test-nffs/sys_config_test-nffs.elf Executing test: ~/dev/myproj/bin/targets/unittest/sys_config_test-nffs/app/sys/config/test-nffs/sys_config_test-nffs.elf Passed tests: [sys/config/test-fcb sys/config/test-nffs] All tests passed Note: If you installed the latest gcc using homebrew on your Mac, you are probably running gcc-6. Make sure you change the compiler.yml configuration to specify that you are using gcc-6 (See Native Install Option ). You can also downgrade your installation to gcc-5 and use the default gcc compiler configuration for MyNewt: $ brew uninstall gcc-6 $ brew link gcc-5 Note: If you are running the standard gcc for 64-bit machines, it does not support 32-bit. In that case you will see compilation errors. You need to install multilib gcc (e.g. gcc-multilib if you running on a 64-bit Ubuntu). To test all the packages in a project, specify all instead of the package name. $ newt test all Testing package @apache-mynewt-core/boot/boot_serial/test Compiling repos/apache-mynewt-core/boot/boot_serial/test/src/boot_test.c Compiling repos/apache-mynewt-core/boot/boot_serial/test/src/testcases/boot_serial_setup.c ... Linking ~/dev/myproj/bin/targets/unittest/boot_boot_serial_test/app/boot/boot_serial/test/boot_boot_serial_test.elf ...lots of compiling and testing... Linking ~/dev/myproj/bin/targets/unittest/util_cbmem_test/app/util/cbmem/test/util_cbmem_test.elf Executing test: ~/dev/myproj/bin/targets/unittest/util_cbmem_test/app/util/cbmem/test/util_cbmem_test.elf Passed tests: [boot/boot_serial/test boot/bootutil/test crypto/mbedtls/test encoding/base64/test encoding/cborattr/test encoding/json/test fs/fcb/test fs/nffs/test kernel/os/test net/ip/mn_socket/test net/nimble/host/test net/oic/test sys/config/test-fcb sys/config/test-nffs sys/flash_map/test sys/log/full/test util/cbmem/test] All tests passed Building and Running the Simulated Blinky Application The section shows you how to build and run the blinky application to run on Mynewt's simulated hardware. Note : This is not yet supported on Windows. Refer to the Blinky Tutorials to create a blinky application for a target board. Building the Application To build the simulated blinky application, run newt build my_blinky_sim : $ newt build my_blinky_sim Building target targets/my_blinky_sim Compiling repos/apache-mynewt-core/hw/hal/src/hal_common.c Compiling repos/apache-mynewt-core/hw/drivers/uart/src/uart.c Compiling repos/apache-mynewt-core/hw/hal/src/hal_flash.c Compiling repos/apache-mynewt-core/hw/bsp/native/src/hal_bsp.c Compiling repos/apache-mynewt-core/hw/drivers/uart/uart_hal/src/uart_hal.c Compiling apps/blinky/src/main.c ... Archiving sys_mfg.a Archiving sys_sysinit.a Archiving util_mem.a Linking ~/dev/myproj/bin/targets/my_blinky_sim/app/apps/blinky/blinky.elf Target successfully built: targets/my_blinky_sim Running the Blinky Application You can run the simulated version of your project and see the simulated LED blink. If you natively install the toolchain execute the binary directly: $ ./bin/targets/my_blinky_sim/app/apps/blinky/blinky.elf hal_gpio set pin 1 to 0 If you are using newt docker, use newt run to run the simulated binary. $ newt run my_blinky_sim Loading app image into slot 1 ... Debugging ~/dev/myproj/bin/targets/my_blinky_sim/app/apps/blinky/blinky.elf ... Reading symbols from /bin/targets/my_blinky_sim/app/apps/blinky/blinky.elf...done. (gdb) Type r at the (gdb) prompt to run the project. You will see an output indicating that the hal_gpio pin is toggling between 1 and 0 in a simulated blink. Exploring other Mynewt OS Features Congratulations, you have created your first project! The blinky application is not terribly exciting when it is run in the simulator, as there is no LED to blink. Apache Mynewt has a lot more functionality than just running simulated applications. It provides all the features you'll need to cross-compile your application, run it on real hardware and develop a full featured application. If you're interested in learning more, a good next step is to dig in to one of the tutorials and get a Mynewt project running on real hardware. Happy Hacking!","title":"Create Your First Project"},{"location":"os/get_started/project_create/#creating-your-first-mynewt-project","text":"This page shows you how to create a Mynewt project using the newt command-line tool. The project is a blinky application that toggles a pin. The application uses the Mynewt's simulated hardware and runs as a native application on Mac OS and Linux. Note: The Mynewt simulator is not yet supported on Windows. If you are using the native install option (not the Docker option), you will need to create the blinky application for a target board. We recommend that you read the section on creating a new project and fetching the source repository to understand the Mynewt repository structure, create a new project, and fetch the source dependencies before proceeding to one of the Blinky Tutorials . This guide shows you how to: Create a new project and fetch the source repository and dependecies. Test the project packages (Not supported on Windows). Build and run the simulated blinky application (Not supported on Windows).","title":"Creating Your First Mynewt Project"},{"location":"os/get_started/project_create/#prerequisites","text":"Have Internet connectivity to fetch remote Mynewt components. Install the newt tool: If you have taken the native install option, see the installation instructions for Mac OS , Linux , or Windows . If you have taken the Docker option, you have already installed Newt. Install the native toolchain to compile and build a Mynewt native application.","title":"Prerequisites"},{"location":"os/get_started/project_create/#creating-a-new-project-and-fetching-the-source-repository","text":"This section describes how to use the newt tool to create a new project and fetch the core mynewt source repository.","title":"Creating a New Project and Fetching the Source Repository"},{"location":"os/get_started/project_create/#creating-a-new-project","text":"Choose a name for your project. We name the project myproj . Run the newt new myproj command, from your dev directory, to create a new project: Note: This tutorial assumes you created a dev directory under your home directory. $cd ~/dev $ newt new myproj Downloading project skeleton from apache/incubator-mynewt-blinky... Installing skeleton in myproj... Project myproj successfully created. The newt tool creates a project base directory name myproj . All newt tool commands are run from the project base directory. The newt tool populates this new project with a base skeleton of a new Apache Mynewt project in the project base directory. It has the following structure: Note : If you do not have tree , run brew install tree to install on Mac OS, sudo apt-get install tree to install on Linux, and pacman -Su tree from a MinGW terminal to install on Windows. $ cd myproj $ tree . \u251c\u2500\u2500 DISCLAIMER \u251c\u2500\u2500 LICENSE \u251c\u2500\u2500 NOTICE \u251c\u2500\u2500 README.md \u251c\u2500\u2500 apps \u2502 \u2514\u2500\u2500 blinky \u2502 \u251c\u2500\u2500 pkg.yml \u2502 \u2514\u2500\u2500 src \u2502 \u2514\u2500\u2500 main.c \u251c\u2500\u2500 project.yml \u2514\u2500\u2500 targets \u251c\u2500\u2500 my_blinky_sim \u2502 \u251c\u2500\u2500 pkg.yml \u2502 \u2514\u2500\u2500 target.yml \u2514\u2500\u2500 unittest \u251c\u2500\u2500 pkg.yml \u2514\u2500\u2500 target.yml 6 directories, 11 files The newt tool installs the following files for a project in the project base directory: The file project.yml contains the repository list that the project uses to fetch its packages. Your project is a collection of repositories. In this case, the project only comprises the core mynewt repository. Later, you will add more repositories to include other mynewt components. The file apps/blinky/pkg.yml contains the description of your application and its package dependencies. A target directory that contains the my_blinky_sim directory. The my_blinky_sim directory a target information to build a version of myproj. Use newt target show to see available build targets. A non-buildable target called unittest . This is used internally by newt and is not a formal build target. Note: The actual code and package files are not installed (except the template for main.c ). See the next step to install the packages.","title":"Creating a New Project"},{"location":"os/get_started/project_create/#fetching-the-mynewt-source-repository-and-dependencies","text":"By default, Mynewt projects rely on a single repository: apache-mynewt-core and uses the source in the master branch. If you need to use a different branch, you need to change the vers value in the project.yml file: repository.apache-mynewt-core: type: github vers: 1-latest user: apache repo: incubator-mynewt-core Changing vers to 0-dev will put you on the latest master branch. This branch may not be stable and you may encounter bugs or other problems. Note: On Windows platforms, you will need to change vers to 0-dev and use the latest master branch. Release 1.0.0 is not supported on Windows. Run the newt install command, from your project base directory (myproj), to fetch the source repository and dependencies: $ newt install apache-mynewt-core Note: It may take a while to download the apache-mynewt-core reposistory. Use the -v (verbose) option to see the installation progress. View the core of the Apache Mynewt OS that is downloaded into your local directory. (The actual output will depend on what is in the latest 'master' branch) $ tree -L 2 repos/apache-mynewt-core/ repos/apache-mynewt-core/ \u251c\u2500\u2500 CODING_STANDARDS.md \u251c\u2500\u2500 DISCLAIMER \u251c\u2500\u2500 LICENSE \u251c\u2500\u2500 NOTICE \u251c\u2500\u2500 README.md \u251c\u2500\u2500 RELEASE_NOTES.md \u251c\u2500\u2500 apps \u2502 \u251c\u2500\u2500 blecent \u2502 \u251c\u2500\u2500 blehci \u2502 \u251c\u2500\u2500 bleprph \u2502 \u251c\u2500\u2500 bleprph_oic \u2502 \u251c\u2500\u2500 blesplit \u2502 \u251c\u2500\u2500 bletest \u2502 \u251c\u2500\u2500 bletiny \u2502 \u251c\u2500\u2500 bleuart \u2502 \u251c\u2500\u2500 boot \u2502 \u251c\u2500\u2500 fat2native \u2502 \u251c\u2500\u2500 ffs2native \u2502 \u251c\u2500\u2500 ocf_sample \u2502 \u251c\u2500\u2500 slinky \u2502 \u251c\u2500\u2500 slinky_oic \u2502 \u251c\u2500\u2500 spitest \u2502 \u251c\u2500\u2500 splitty \u2502 \u251c\u2500\u2500 test \u2502 \u251c\u2500\u2500 testbench \u2502 \u2514\u2500\u2500 timtest \u251c\u2500\u2500 boot \u2502 \u251c\u2500\u2500 boot_serial \u2502 \u251c\u2500\u2500 bootutil \u2502 \u251c\u2500\u2500 split \u2502 \u2514\u2500\u2500 split_app \u251c\u2500\u2500 compiler \u2502 \u251c\u2500\u2500 arm-none-eabi-m0 \u2502 \u251c\u2500\u2500 arm-none-eabi-m4 \u2502 \u251c\u2500\u2500 gdbmacros \u2502 \u251c\u2500\u2500 mips \u2502 \u251c\u2500\u2500 sim \u2502 \u2514\u2500\u2500 sim-mips \u251c\u2500\u2500 crypto \u2502 \u251c\u2500\u2500 mbedtls \u2502 \u2514\u2500\u2500 tinycrypt \u251c\u2500\u2500 docs \u2502 \u2514\u2500\u2500 doxygen.xml \u251c\u2500\u2500 encoding \u2502 \u251c\u2500\u2500 base64 \u2502 \u251c\u2500\u2500 cborattr \u2502 \u251c\u2500\u2500 json \u2502 \u2514\u2500\u2500 tinycbor \u251c\u2500\u2500 fs \u2502 \u251c\u2500\u2500 disk \u2502 \u251c\u2500\u2500 fatfs \u2502 \u251c\u2500\u2500 fcb \u2502 \u251c\u2500\u2500 fs \u2502 \u2514\u2500\u2500 nffs \u251c\u2500\u2500 hw \u2502 \u251c\u2500\u2500 bsp \u2502 \u251c\u2500\u2500 cmsis-core \u2502 \u251c\u2500\u2500 drivers \u2502 \u251c\u2500\u2500 hal \u2502 \u251c\u2500\u2500 mcu \u2502 \u2514\u2500\u2500 scripts \u251c\u2500\u2500 kernel \u2502 \u2514\u2500\u2500 os \u251c\u2500\u2500 libc \u2502 \u2514\u2500\u2500 baselibc \u251c\u2500\u2500 mgmt \u2502 \u251c\u2500\u2500 imgmgr \u2502 \u251c\u2500\u2500 mgmt \u2502 \u251c\u2500\u2500 newtmgr \u2502 \u2514\u2500\u2500 oicmgr \u251c\u2500\u2500 net \u2502 \u251c\u2500\u2500 ip \u2502 \u251c\u2500\u2500 nimble \u2502 \u251c\u2500\u2500 oic \u2502 \u2514\u2500\u2500 wifi \u251c\u2500\u2500 project.yml \u251c\u2500\u2500 repository.yml \u251c\u2500\u2500 sys \u2502 \u251c\u2500\u2500 config \u2502 \u251c\u2500\u2500 console \u2502 \u251c\u2500\u2500 coredump \u2502 \u251c\u2500\u2500 defs \u2502 \u251c\u2500\u2500 flash_map \u2502 \u251c\u2500\u2500 id \u2502 \u251c\u2500\u2500 log \u2502 \u251c\u2500\u2500 mfg \u2502 \u251c\u2500\u2500 reboot \u2502 \u251c\u2500\u2500 shell \u2502 \u251c\u2500\u2500 stats \u2502 \u2514\u2500\u2500 sysinit \u251c\u2500\u2500 targets \u2502 \u2514\u2500\u2500 unittest \u251c\u2500\u2500 test \u2502 \u251c\u2500\u2500 crash_test \u2502 \u251c\u2500\u2500 flash_test \u2502 \u251c\u2500\u2500 runtest \u2502 \u2514\u2500\u2500 testutil \u251c\u2500\u2500 time \u2502 \u2514\u2500\u2500 datetime \u2514\u2500\u2500 util \u251c\u2500\u2500 cbmem \u251c\u2500\u2500 crc \u2514\u2500\u2500 mem 94 directories, 9 files","title":"Fetching the Mynewt Source Repository and Dependencies"},{"location":"os/get_started/project_create/#testing-the-project-packages","text":"Note : This is not yet supported on Windows. You can use the newt tool to execute the unit tests in a package. For example, run the following command to test the sys/config package in the apache-mynewt-core repo: $ newt test @apache-mynewt-core/sys/config Testing package @apache-mynewt-core/sys/config/test-fcb Compiling bootutil_misc.c Compiling image_ec.c Compiling image_rsa.c Compiling image_validate.c ... Linking ~/dev/myproj/bin/targets/unittest/sys_config_test-fcb/app/sys/config/test-fcb/sys_config_test-fcb.elf Executing test: ~/dev/myproj/bin/targets/unittest/sys_config_test-fcb/app/sys/config/test-fcb/sys_config_test-fcb.elf Testing package @apache-mynewt-core/sys/config/test-nffs Compiling repos/apache-mynewt-core/encoding/base64/src/hex.c Compiling repos/apache-mynewt-core/fs/fs/src/fs_cli.c Compiling repos/apache-mynewt-core/fs/fs/src/fs_dirent.c Compiling repos/apache-mynewt-core/fs/fs/src/fs_mkdir.c Compiling repos/apache-mynewt-core/fs/fs/src/fs_mount.c Compiling repos/apache-mynewt-core/encoding/base64/src/base64.c Compiling repos/apache-mynewt-core/fs/fs/src/fs_file.c Compiling repos/apache-mynewt-core/fs/disk/src/disk.c Compiling repos/apache-mynewt-core/fs/fs/src/fs_nmgr.c Compiling repos/apache-mynewt-core/fs/fs/src/fsutil.c Compiling repos/apache-mynewt-core/fs/nffs/src/nffs.c ... Linking ~/dev/myproj/bin/targets/unittest/sys_config_test-nffs/app/sys/config/test-nffs/sys_config_test-nffs.elf Executing test: ~/dev/myproj/bin/targets/unittest/sys_config_test-nffs/app/sys/config/test-nffs/sys_config_test-nffs.elf Passed tests: [sys/config/test-fcb sys/config/test-nffs] All tests passed Note: If you installed the latest gcc using homebrew on your Mac, you are probably running gcc-6. Make sure you change the compiler.yml configuration to specify that you are using gcc-6 (See Native Install Option ). You can also downgrade your installation to gcc-5 and use the default gcc compiler configuration for MyNewt: $ brew uninstall gcc-6 $ brew link gcc-5 Note: If you are running the standard gcc for 64-bit machines, it does not support 32-bit. In that case you will see compilation errors. You need to install multilib gcc (e.g. gcc-multilib if you running on a 64-bit Ubuntu). To test all the packages in a project, specify all instead of the package name. $ newt test all Testing package @apache-mynewt-core/boot/boot_serial/test Compiling repos/apache-mynewt-core/boot/boot_serial/test/src/boot_test.c Compiling repos/apache-mynewt-core/boot/boot_serial/test/src/testcases/boot_serial_setup.c ... Linking ~/dev/myproj/bin/targets/unittest/boot_boot_serial_test/app/boot/boot_serial/test/boot_boot_serial_test.elf ...lots of compiling and testing... Linking ~/dev/myproj/bin/targets/unittest/util_cbmem_test/app/util/cbmem/test/util_cbmem_test.elf Executing test: ~/dev/myproj/bin/targets/unittest/util_cbmem_test/app/util/cbmem/test/util_cbmem_test.elf Passed tests: [boot/boot_serial/test boot/bootutil/test crypto/mbedtls/test encoding/base64/test encoding/cborattr/test encoding/json/test fs/fcb/test fs/nffs/test kernel/os/test net/ip/mn_socket/test net/nimble/host/test net/oic/test sys/config/test-fcb sys/config/test-nffs sys/flash_map/test sys/log/full/test util/cbmem/test] All tests passed","title":"Testing the Project Packages"},{"location":"os/get_started/project_create/#building-and-running-the-simulated-blinky-application","text":"The section shows you how to build and run the blinky application to run on Mynewt's simulated hardware. Note : This is not yet supported on Windows. Refer to the Blinky Tutorials to create a blinky application for a target board.","title":"Building and Running the Simulated Blinky Application"},{"location":"os/get_started/project_create/#building-the-application","text":"To build the simulated blinky application, run newt build my_blinky_sim : $ newt build my_blinky_sim Building target targets/my_blinky_sim Compiling repos/apache-mynewt-core/hw/hal/src/hal_common.c Compiling repos/apache-mynewt-core/hw/drivers/uart/src/uart.c Compiling repos/apache-mynewt-core/hw/hal/src/hal_flash.c Compiling repos/apache-mynewt-core/hw/bsp/native/src/hal_bsp.c Compiling repos/apache-mynewt-core/hw/drivers/uart/uart_hal/src/uart_hal.c Compiling apps/blinky/src/main.c ... Archiving sys_mfg.a Archiving sys_sysinit.a Archiving util_mem.a Linking ~/dev/myproj/bin/targets/my_blinky_sim/app/apps/blinky/blinky.elf Target successfully built: targets/my_blinky_sim","title":"Building the Application"},{"location":"os/get_started/project_create/#running-the-blinky-application","text":"You can run the simulated version of your project and see the simulated LED blink. If you natively install the toolchain execute the binary directly: $ ./bin/targets/my_blinky_sim/app/apps/blinky/blinky.elf hal_gpio set pin 1 to 0 If you are using newt docker, use newt run to run the simulated binary. $ newt run my_blinky_sim Loading app image into slot 1 ... Debugging ~/dev/myproj/bin/targets/my_blinky_sim/app/apps/blinky/blinky.elf ... Reading symbols from /bin/targets/my_blinky_sim/app/apps/blinky/blinky.elf...done. (gdb) Type r at the (gdb) prompt to run the project. You will see an output indicating that the hal_gpio pin is toggling between 1 and 0 in a simulated blink.","title":"Running the Blinky Application"},{"location":"os/get_started/project_create/#exploring-other-mynewt-os-features","text":"Congratulations, you have created your first project! The blinky application is not terribly exciting when it is run in the simulator, as there is no LED to blink. Apache Mynewt has a lot more functionality than just running simulated applications. It provides all the features you'll need to cross-compile your application, run it on real hardware and develop a full featured application. If you're interested in learning more, a good next step is to dig in to one of the tutorials and get a Mynewt project running on real hardware. Happy Hacking!","title":"Exploring other Mynewt OS Features"},{"location":"os/get_started/serial_access/","text":"Using the Serial Port with Mynewt OS Some of the projects and tutorials here will allow you to use a serial port to interact with your Mynewt project. While most modern PCs and laptops no longer have a true serial port, almost all can use their USB ports as serial ports. This will show you how to connect to some of the development boards we use via a serial port. The development boards covered here are: Nordic Semiconductor NRF52dk Arduino M0 Pro In order to communicate with these boards you will also need a USB<-->Serial converted. We'll be using the AdaFruit FT232H Breakout Board for this, but almost any similar board should work just as well. You will also need Minicom or a similar Serial communications application. We'll show you how to use the screen command built in to Mac OS X, but later tutorials will also show Minicom setup. So let's get started! Setup FT232H This is a great board because it's so easy to set up, and it can do Serial UART, SPI, I2C and GPIO as well. There's full documentation on the board here but we're only covering the wiring for the Serial UART. Start by connecting a jumper wire to Pin D0. This will be the UART Tx pin, which we'll then connect to the Rx pin on the Development Board. Next connect a jumper wire to pin D1. This will be the UART Rx pin, which we'll connect to the Tx pin on the development board. Finally connect a jumper wire to the GND pin. It should look like this: Setup Nordic Semiconductor NRF52DK On the NRF52DK developer kit board, the Rx pin is P0.08, so you'll attach your jumper wire from the Tx pin (D0) of the FT232H board here. The TX Pin is pin P0.06, so you'll attache the jumper wire from the Rx Pin (D1) on the FT232H board here. Finally, the GND wire should go to the GND Pin on the NRF52DK. When you're done, your wiring should look like this: Setup Arduino M0 Pro On the Arduino M0 Pro, the Tx and Rx pins are clearly labeled as such, as is the GND pin. Just make sure you wire Rx from the FT232H to TX on the M0 Pro, and vice-versa. Your Arduino M0 Pro should look like this: Setup Serial Communications You will need to know the serial port to connect to and use a terminal program to connect to the board. Example for Mac OS and Linux Platforms First check what USB devices are already connected before connecting the FT232H board to your computer. The ports are listed in the /dev directory and the format of the port name is platform dependent: Mac OS uses the format tty.usbserial-<some identifier> . Linux uses the format TTYUSB<N> , where N is a number. For example, TTYUSB2. This example is run on a Mac OS system. Check what USB devices are already connected: $ ls -la /dev/*usb* 0 crw-rw-rw- 1 root wheel 20, 63 Nov 23 11:13 /dev/cu.usbmodem401322 0 crw-rw-rw- 1 root wheel 20, 62 Nov 23 11:13 /dev/tty.usbmodem401322 $ Plug in the FT232H board and check the ports again: $ ls -la /dev/*usb* 0 crw-rw-rw- 1 root wheel 20, 63 Nov 23 11:13 /dev/cu.usbmodem401322 0 crw-rw-rw- 1 root wheel 20, 65 Nov 23 11:26 /dev/cu.usbserial-0020124 0 crw-rw-rw- 1 root wheel 20, 62 Nov 23 11:13 /dev/tty.usbmodem401322 0 crw-rw-rw- 1 root wheel 20, 64 Nov 23 11:26 /dev/tty.usbserial-0020124 $ The FT232H is connected to /dev/tty.usbserial-0020124 (The number after tty.usbserial will be different on your machine.) Use the screen command to connect to the board: $ screen /dev/tty.usbserial-0020124 115200 To exit out of screen you'll type control-A followed by control-\\ and you'll be back to a terminal prompt. You can also use minicom: $ minicom -D /dev/tty.usbserial-0020124 Welcome to minicom 2.7 OPTIONS: Compiled on Nov 24 2015, 16:14:21. Port /dev/tty.usbserial-0020124, 09:57:17 Press Meta-Z for help on special keys If there's no Mynewt app running, or the Mynewt app doesn't have the Shell and Console enabled, you won't see anything there, but you can always refer back to this page from later tutorials if you need to. Example for Windows Platforms First check what USB devices are already connected before connecting the FT232H board to your computer. You can locate the ports from a MinGW terminal or use the Windows Device Manager. On a MinGW terminal, the ports are listed in the /dev directory and the format of the port name is ttyS<N> where N is a number. You must map the port name to a Windows COM port: /dev/ttyS<N> maps to COM<N+1> . For example, /dev/ttyS2 maps to COM3 . Check what USB devices are already connected: $ls -l /dev/ttyS* crw-rw-rw- 1 <user> None 117, 5 May 9 04:24 /dev/ttyS5 $ /dev/ttyS5 maps to the Windows COM6 port. You can run Windows Device Manager to confirm: Plug in the FT232H board and check the ports again: $ls -l /dev/ttyS* ls -l /dev/ttyS* crw-rw-rw- 1 <user> None 117, 10 May 9 04:55 /dev/ttyS10 crw-rw-rw- 1 <user> None 117, 5 May 9 04:55 /dev/ttyS5 $ The FT232H board is connected to port /dev/ttyS10 (or COM11): We use the PuTTY terminal application to connect to the board on the COM11 port: Press Open and you should get a terminal screen titled \"COM11 - PuTTY\" If there's no Mynewt app running, or the Mynewt app doesn't have the Shell and Console enabled, you won't see anything there, but you can always refer back to this page from later tutorials if you need to. Now that you know how to communicate with your mynewt application, let's move on to creating one!","title":"Serial Port Setup"},{"location":"os/get_started/serial_access/#using-the-serial-port-with-mynewt-os","text":"Some of the projects and tutorials here will allow you to use a serial port to interact with your Mynewt project. While most modern PCs and laptops no longer have a true serial port, almost all can use their USB ports as serial ports. This will show you how to connect to some of the development boards we use via a serial port. The development boards covered here are: Nordic Semiconductor NRF52dk Arduino M0 Pro In order to communicate with these boards you will also need a USB<-->Serial converted. We'll be using the AdaFruit FT232H Breakout Board for this, but almost any similar board should work just as well. You will also need Minicom or a similar Serial communications application. We'll show you how to use the screen command built in to Mac OS X, but later tutorials will also show Minicom setup. So let's get started!","title":"Using the Serial Port with Mynewt OS"},{"location":"os/get_started/serial_access/#setup-ft232h","text":"This is a great board because it's so easy to set up, and it can do Serial UART, SPI, I2C and GPIO as well. There's full documentation on the board here but we're only covering the wiring for the Serial UART. Start by connecting a jumper wire to Pin D0. This will be the UART Tx pin, which we'll then connect to the Rx pin on the Development Board. Next connect a jumper wire to pin D1. This will be the UART Rx pin, which we'll connect to the Tx pin on the development board. Finally connect a jumper wire to the GND pin. It should look like this:","title":"Setup FT232H"},{"location":"os/get_started/serial_access/#setup-nordic-semiconductor-nrf52dk","text":"On the NRF52DK developer kit board, the Rx pin is P0.08, so you'll attach your jumper wire from the Tx pin (D0) of the FT232H board here. The TX Pin is pin P0.06, so you'll attache the jumper wire from the Rx Pin (D1) on the FT232H board here. Finally, the GND wire should go to the GND Pin on the NRF52DK. When you're done, your wiring should look like this:","title":"Setup Nordic Semiconductor NRF52DK"},{"location":"os/get_started/serial_access/#setup-arduino-m0-pro","text":"On the Arduino M0 Pro, the Tx and Rx pins are clearly labeled as such, as is the GND pin. Just make sure you wire Rx from the FT232H to TX on the M0 Pro, and vice-versa. Your Arduino M0 Pro should look like this:","title":"Setup Arduino M0 Pro"},{"location":"os/get_started/serial_access/#setup-serial-communications","text":"You will need to know the serial port to connect to and use a terminal program to connect to the board.","title":"Setup Serial Communications"},{"location":"os/get_started/serial_access/#example-for-mac-os-and-linux-platforms","text":"First check what USB devices are already connected before connecting the FT232H board to your computer. The ports are listed in the /dev directory and the format of the port name is platform dependent: Mac OS uses the format tty.usbserial-<some identifier> . Linux uses the format TTYUSB<N> , where N is a number. For example, TTYUSB2. This example is run on a Mac OS system. Check what USB devices are already connected: $ ls -la /dev/*usb* 0 crw-rw-rw- 1 root wheel 20, 63 Nov 23 11:13 /dev/cu.usbmodem401322 0 crw-rw-rw- 1 root wheel 20, 62 Nov 23 11:13 /dev/tty.usbmodem401322 $ Plug in the FT232H board and check the ports again: $ ls -la /dev/*usb* 0 crw-rw-rw- 1 root wheel 20, 63 Nov 23 11:13 /dev/cu.usbmodem401322 0 crw-rw-rw- 1 root wheel 20, 65 Nov 23 11:26 /dev/cu.usbserial-0020124 0 crw-rw-rw- 1 root wheel 20, 62 Nov 23 11:13 /dev/tty.usbmodem401322 0 crw-rw-rw- 1 root wheel 20, 64 Nov 23 11:26 /dev/tty.usbserial-0020124 $ The FT232H is connected to /dev/tty.usbserial-0020124 (The number after tty.usbserial will be different on your machine.) Use the screen command to connect to the board: $ screen /dev/tty.usbserial-0020124 115200 To exit out of screen you'll type control-A followed by control-\\ and you'll be back to a terminal prompt. You can also use minicom: $ minicom -D /dev/tty.usbserial-0020124 Welcome to minicom 2.7 OPTIONS: Compiled on Nov 24 2015, 16:14:21. Port /dev/tty.usbserial-0020124, 09:57:17 Press Meta-Z for help on special keys If there's no Mynewt app running, or the Mynewt app doesn't have the Shell and Console enabled, you won't see anything there, but you can always refer back to this page from later tutorials if you need to.","title":"Example for Mac OS and Linux Platforms"},{"location":"os/get_started/serial_access/#example-for-windows-platforms","text":"First check what USB devices are already connected before connecting the FT232H board to your computer. You can locate the ports from a MinGW terminal or use the Windows Device Manager. On a MinGW terminal, the ports are listed in the /dev directory and the format of the port name is ttyS<N> where N is a number. You must map the port name to a Windows COM port: /dev/ttyS<N> maps to COM<N+1> . For example, /dev/ttyS2 maps to COM3 . Check what USB devices are already connected: $ls -l /dev/ttyS* crw-rw-rw- 1 <user> None 117, 5 May 9 04:24 /dev/ttyS5 $ /dev/ttyS5 maps to the Windows COM6 port. You can run Windows Device Manager to confirm: Plug in the FT232H board and check the ports again: $ls -l /dev/ttyS* ls -l /dev/ttyS* crw-rw-rw- 1 <user> None 117, 10 May 9 04:55 /dev/ttyS10 crw-rw-rw- 1 <user> None 117, 5 May 9 04:55 /dev/ttyS5 $ The FT232H board is connected to port /dev/ttyS10 (or COM11): We use the PuTTY terminal application to connect to the board on the COM11 port: Press Open and you should get a terminal screen titled \"COM11 - PuTTY\" If there's no Mynewt app running, or the Mynewt app doesn't have the Shell and Console enabled, you won't see anything there, but you can always refer back to this page from later tutorials if you need to. Now that you know how to communicate with your mynewt application, let's move on to creating one!","title":"Example for Windows Platforms"},{"location":"os/get_started/vocabulary/","text":"Concepts This page is meant to introduce you to some of the concepts inherent to the Apache Mynewt Operating System, and Newt the tool that stitches a project built on Apache Mynewt together. Project The project is the base directory of your embedded software tree. It is a workspace that contains a logical collection of source code, for one or more of your applications. A project consists of the following items: Project Definition: defines project level dependencies, and parameters (located in project.yml ) Packages Packages are described in detail in the section below. Here is an example project definition file from the default Apache Mynewt project: $ more project.yml <snip> project.name: \"my_project\" project.repositories: - apache-mynewt-core # Use github's distribution mechanism for core ASF libraries. # This provides mirroring automatically for us. # repository.apache-mynewt-core: type: github vers: 1-latest user: apache repo: incubator-mynewt-core $ A couple of things to note in the project definition: project.repositories : Defines the remote repositories that this project relies upon. repository.apache-mynewt-core : Defines the repository information for the apache-mynewt-core repository. vers=1-latest : Defines the repository version. This string will use the latest stable version in the 'Master' github branch. To use the latest version in the master branch, just change it to vers=0-dev . Note that this branch might not be stable. Repositories are versioned collections of packages. Projects can rely on remote repositories for functionality, and the newt tool will resolve those remote repositories, and download the correct version into your local source tree. Newly fetched repositories are put in the repos directory of your project, and can be referenced throughout the system by using the @ specifier. By default, the @apache-mynewt-core repository is included in every project. Apache Mynewt Core contains all the base functionality of the Apache Mynewt Operating System, including the Real Time Kernel, Bluetooth Networking Stack, Flash File System, Console, Shell and Bootloader. NOTE: Any project can be converted into a repository by providing it with a repository.yml file and putting it up onto Github. More information about repositories can be found in the Newt documentation. Package A package is a collection items that form a fundamental unit in the Mynewt Operating System. Packages can be: Applications Libraries Compiler definitions Targets A package is identified by having a pkg.yml file in it's base directory. Here is a sample pkg.yml file for the blinky applicaton: $ more pkg.yml <snip> pkg.name: apps/blinky pkg.type: app pkg.description: Basic example application which blinks an LED. pkg.author: \"Apache Mynewt <dev@mynewt.incubator.apache.org>\" pkg.homepage: \"http://mynewt.apache.org/\" pkg.keywords: pkg.deps: - \"@apache-mynewt-core/libs/os\" - \"@apache-mynewt-core/hw/hal\" - \"@apache-mynewt-core/libs/console/full\" Packages have a few features worth noting: Dependencies: Packages can rely upon other packages, and when they do they will inherit their functionality (header files, library definitions, etc.) APIs: Packages can export named APIs, and they can require that certain APIs be present, in order to compile. Everything that newt knows about within a project's directory is a package. This makes it very clean and easy to write re-usable components, which can describe their Dependencies and APIs to the rest of the system. Target A target in Apache Mynewt is very similar to a target in make . It is the collection of parameters that must be passed to Newt in order to generate a reproducible build. A target represents the top of the build tree, and any packages or parameters specified at the target level, cascade down to all dependencies. Targets are also packages, and are stored in the targets/ directory at the base of your project. Most targets consist of: app : The application to build. bsp : The board support package to combine with that application build_profile : Either debug or optimized . Targets can also have additional items specified, including: aflags : Any additional assembler flags you might want to specify to the build. cflags : Any additional compiler flags you might want to specify to the build. lflags : Any additional linker flags you might want to specify to the build. In order to create and manipulate targets, the newt tool offers a set of helper commands, you can find more information about these by issuing: $ newt target newt target Usage: newt target [flags] newt target [command] Available Commands: config View or populate a target's system configuration copy Copy target create Create a target delete Delete target dep View target's dependency graph revdep View target's reverse-dependency graph set Set target configuration variable show View target configuration variables Global Flags: -h, --help Help for newt commands -j, --jobs int Number of concurrent build jobs (default 8) -l, --loglevel string Log level (default \"WARN\") -o, --outfile string Filename to tee output to -q, --quiet Be quiet; only display error output -s, --silent Be silent; don't output anything -v, --verbose Enable verbose output when executing commands Use \"newt target [command] --help\" for more information about a command. $ Configuration There are a lot of configuration options available when building your application in MyNewt. System Configuration options are set in a file called syscfg.yml and you will find these configuration files throughout the MyNewt packages. While you can edit these files directly to change some default settings, it is best to override the default settings in a syscfg.yml file in your project directory rather than editing the package configurations directly. To see all all the system configuration settings, simply type $ newt target config show <target-name> ... * PACKAGE: sys/stats * Setting: STATS_CLI * Description: Expose the \"stat\" shell command. * Value: 0 * Setting: STATS_NAMES * Description: Include and report the textual name of each statistic. * Value: 0 * Setting: STATS_NEWTMGR * Description: Expose the \"stat\" newtmgr command. * Value: 0 ... $ Keep in mind that this will only show the configuration options for any packages that are included in your applicaiton. If you really want to see all the available configuration options, you can go rough each package and look at the syscfg.yml file in each.","title":"Concepts"},{"location":"os/get_started/vocabulary/#concepts","text":"This page is meant to introduce you to some of the concepts inherent to the Apache Mynewt Operating System, and Newt the tool that stitches a project built on Apache Mynewt together.","title":"Concepts"},{"location":"os/get_started/vocabulary/#project","text":"The project is the base directory of your embedded software tree. It is a workspace that contains a logical collection of source code, for one or more of your applications. A project consists of the following items: Project Definition: defines project level dependencies, and parameters (located in project.yml ) Packages Packages are described in detail in the section below. Here is an example project definition file from the default Apache Mynewt project: $ more project.yml <snip> project.name: \"my_project\" project.repositories: - apache-mynewt-core # Use github's distribution mechanism for core ASF libraries. # This provides mirroring automatically for us. # repository.apache-mynewt-core: type: github vers: 1-latest user: apache repo: incubator-mynewt-core $ A couple of things to note in the project definition: project.repositories : Defines the remote repositories that this project relies upon. repository.apache-mynewt-core : Defines the repository information for the apache-mynewt-core repository. vers=1-latest : Defines the repository version. This string will use the latest stable version in the 'Master' github branch. To use the latest version in the master branch, just change it to vers=0-dev . Note that this branch might not be stable. Repositories are versioned collections of packages. Projects can rely on remote repositories for functionality, and the newt tool will resolve those remote repositories, and download the correct version into your local source tree. Newly fetched repositories are put in the repos directory of your project, and can be referenced throughout the system by using the @ specifier. By default, the @apache-mynewt-core repository is included in every project. Apache Mynewt Core contains all the base functionality of the Apache Mynewt Operating System, including the Real Time Kernel, Bluetooth Networking Stack, Flash File System, Console, Shell and Bootloader. NOTE: Any project can be converted into a repository by providing it with a repository.yml file and putting it up onto Github. More information about repositories can be found in the Newt documentation.","title":"Project"},{"location":"os/get_started/vocabulary/#package","text":"A package is a collection items that form a fundamental unit in the Mynewt Operating System. Packages can be: Applications Libraries Compiler definitions Targets A package is identified by having a pkg.yml file in it's base directory. Here is a sample pkg.yml file for the blinky applicaton: $ more pkg.yml <snip> pkg.name: apps/blinky pkg.type: app pkg.description: Basic example application which blinks an LED. pkg.author: \"Apache Mynewt <dev@mynewt.incubator.apache.org>\" pkg.homepage: \"http://mynewt.apache.org/\" pkg.keywords: pkg.deps: - \"@apache-mynewt-core/libs/os\" - \"@apache-mynewt-core/hw/hal\" - \"@apache-mynewt-core/libs/console/full\" Packages have a few features worth noting: Dependencies: Packages can rely upon other packages, and when they do they will inherit their functionality (header files, library definitions, etc.) APIs: Packages can export named APIs, and they can require that certain APIs be present, in order to compile. Everything that newt knows about within a project's directory is a package. This makes it very clean and easy to write re-usable components, which can describe their Dependencies and APIs to the rest of the system.","title":"Package"},{"location":"os/get_started/vocabulary/#target","text":"A target in Apache Mynewt is very similar to a target in make . It is the collection of parameters that must be passed to Newt in order to generate a reproducible build. A target represents the top of the build tree, and any packages or parameters specified at the target level, cascade down to all dependencies. Targets are also packages, and are stored in the targets/ directory at the base of your project. Most targets consist of: app : The application to build. bsp : The board support package to combine with that application build_profile : Either debug or optimized . Targets can also have additional items specified, including: aflags : Any additional assembler flags you might want to specify to the build. cflags : Any additional compiler flags you might want to specify to the build. lflags : Any additional linker flags you might want to specify to the build. In order to create and manipulate targets, the newt tool offers a set of helper commands, you can find more information about these by issuing: $ newt target newt target Usage: newt target [flags] newt target [command] Available Commands: config View or populate a target's system configuration copy Copy target create Create a target delete Delete target dep View target's dependency graph revdep View target's reverse-dependency graph set Set target configuration variable show View target configuration variables Global Flags: -h, --help Help for newt commands -j, --jobs int Number of concurrent build jobs (default 8) -l, --loglevel string Log level (default \"WARN\") -o, --outfile string Filename to tee output to -q, --quiet Be quiet; only display error output -s, --silent Be silent; don't output anything -v, --verbose Enable verbose output when executing commands Use \"newt target [command] --help\" for more information about a command. $","title":"Target"},{"location":"os/get_started/vocabulary/#configuration","text":"There are a lot of configuration options available when building your application in MyNewt. System Configuration options are set in a file called syscfg.yml and you will find these configuration files throughout the MyNewt packages. While you can edit these files directly to change some default settings, it is best to override the default settings in a syscfg.yml file in your project directory rather than editing the package configurations directly. To see all all the system configuration settings, simply type $ newt target config show <target-name> ... * PACKAGE: sys/stats * Setting: STATS_CLI * Description: Expose the \"stat\" shell command. * Value: 0 * Setting: STATS_NAMES * Description: Include and report the textual name of each statistic. * Value: 0 * Setting: STATS_NEWTMGR * Description: Expose the \"stat\" newtmgr command. * Value: 0 ... $ Keep in mind that this will only show the configuration options for any packages that are included in your applicaiton. If you really want to see all the available configuration options, you can go rough each package and look at the syscfg.yml file in each.","title":"Configuration"},{"location":"os/modules/baselibc/","text":"Baselibc Baselibc is a very simple libc for embedded systems geared primarily for 32-bit microcontrollers in the 10-100kB memory range. The library of basic system calls and facilities compiles to less than 5kB total on Cortex-M3, and much less if some functions aren't used. The code is based on klibc and tinyprintf modules, and licensed under the BSD license. Baselibc comes from https://github.com/PetteriAimonen/Baselibc.git Description Mynewt OS can utilize libc which comes with the compiler (e.g. newlib bundled with some binary distributions of arm-none-eabi-gcc). However, you may choose to replace the libc with baselibc for a reduced image size. Baselibc optimizes for size rather than performance, which is usually a more important goal in embedded environments. How to switch to baselibc In order to switch from using libc to using baselibc you have to add the baselibc pkg as a dependency in the project pkg. Specifying this dependency ensures that the linker first looks for the functions in baselibc before falling back to libc while creating the executable. For example, project boot uses baselibc. Its project description file boot.yml looks like the following: project.name: boot project.identities: bootloader project.pkgs: - libs/os - libs/bootutil - libs/nffs - libs/console/stub - libs/util - libs/baselibc List of Functions Documentation for libc functions is available from multiple places. One example is the on-line manual pages at https://www.freebsd.org/cgi/man.cgi . baselibc supports most libc functionality; malloc() , printf-family, string handling, and conversion routines. There is some functionality which is not available, e.g. support for floating point numbers, and limited support for 'long long'.","title":"Baselibc library"},{"location":"os/modules/baselibc/#baselibc","text":"Baselibc is a very simple libc for embedded systems geared primarily for 32-bit microcontrollers in the 10-100kB memory range. The library of basic system calls and facilities compiles to less than 5kB total on Cortex-M3, and much less if some functions aren't used. The code is based on klibc and tinyprintf modules, and licensed under the BSD license. Baselibc comes from https://github.com/PetteriAimonen/Baselibc.git","title":"Baselibc"},{"location":"os/modules/baselibc/#description","text":"Mynewt OS can utilize libc which comes with the compiler (e.g. newlib bundled with some binary distributions of arm-none-eabi-gcc). However, you may choose to replace the libc with baselibc for a reduced image size. Baselibc optimizes for size rather than performance, which is usually a more important goal in embedded environments.","title":"Description"},{"location":"os/modules/baselibc/#how-to-switch-to-baselibc","text":"In order to switch from using libc to using baselibc you have to add the baselibc pkg as a dependency in the project pkg. Specifying this dependency ensures that the linker first looks for the functions in baselibc before falling back to libc while creating the executable. For example, project boot uses baselibc. Its project description file boot.yml looks like the following: project.name: boot project.identities: bootloader project.pkgs: - libs/os - libs/bootutil - libs/nffs - libs/console/stub - libs/util - libs/baselibc","title":"How to switch to baselibc"},{"location":"os/modules/baselibc/#list-of-functions","text":"Documentation for libc functions is available from multiple places. One example is the on-line manual pages at https://www.freebsd.org/cgi/man.cgi . baselibc supports most libc functionality; malloc() , printf-family, string handling, and conversion routines. There is some functionality which is not available, e.g. support for floating point numbers, and limited support for 'long long'.","title":"List of Functions"},{"location":"os/modules/bootloader/boot_build_status/","text":"","title":"boot_build_status"},{"location":"os/modules/bootloader/boot_build_status_one/","text":"","title":"boot_build_status_one"},{"location":"os/modules/bootloader/boot_clear_status/","text":"","title":"boot_clear_status"},{"location":"os/modules/bootloader/boot_copy_area/","text":"","title":"boot_copy_area"},{"location":"os/modules/bootloader/boot_copy_image/","text":"","title":"boot_copy_image"},{"location":"os/modules/bootloader/boot_erase_area/","text":"","title":"boot_erase_area"},{"location":"os/modules/bootloader/boot_fill_slot/","text":"","title":"boot_fill_slot"},{"location":"os/modules/bootloader/boot_find_image_area_idx/","text":"","title":"boot_find_image_area_idx"},{"location":"os/modules/bootloader/boot_find_image_part/","text":"","title":"boot_find_image_part"},{"location":"os/modules/bootloader/boot_find_image_slot/","text":"","title":"boot_find_image_slot"},{"location":"os/modules/bootloader/boot_go/","text":"","title":"boot_go"},{"location":"os/modules/bootloader/boot_init_flash/","text":"","title":"boot_init_flash"},{"location":"os/modules/bootloader/boot_move_area/","text":"","title":"boot_move_area"},{"location":"os/modules/bootloader/boot_read_image_header/","text":"","title":"boot_read_image_header"},{"location":"os/modules/bootloader/boot_read_image_headers/","text":"","title":"boot_read_image_headers"},{"location":"os/modules/bootloader/boot_read_status/","text":"","title":"boot_read_status"},{"location":"os/modules/bootloader/boot_select_image_slot/","text":"","title":"boot_select_image_slot"},{"location":"os/modules/bootloader/boot_slot_addr/","text":"","title":"boot_slot_addr"},{"location":"os/modules/bootloader/boot_slot_to_area_idx/","text":"","title":"boot_slot_to_area_idx"},{"location":"os/modules/bootloader/boot_swap_areas/","text":"","title":"boot_swap_areas"},{"location":"os/modules/bootloader/boot_vect_delete_main/","text":"","title":"boot_vect_delete_main"},{"location":"os/modules/bootloader/boot_vect_delete_test/","text":"","title":"boot_vect_delete_test"},{"location":"os/modules/bootloader/boot_vect_read_main/","text":"","title":"boot_vect_read_main"},{"location":"os/modules/bootloader/boot_vect_read_one/","text":"","title":"boot_vect_read_one"},{"location":"os/modules/bootloader/boot_vect_read_test/","text":"","title":"boot_vect_read_test"},{"location":"os/modules/bootloader/boot_write_status/","text":"","title":"boot_write_status"},{"location":"os/modules/bootloader/bootloader/","text":"Bootloader The \"bootloader\" is the code that loads the Mynewt OS image into memory and conducts some checks before allowing the OS to be run. It manages images for the embedded system and upgrades of those images using protocols over various interfaces (e.g. serial, BLE, etc.). Typically, systems with bootloaders have at least two program images coexisting on the same microcontroller, and hence must include branch code that performs a check to see if an attempt to update software is already underway and manage the progress of the process. The bootloader in the Apache Mynewt project verifies the cryptographic signature of the firmware image before running it. It maintains a detailed status log for each stage of the boot process. For verification of the authenticity of the OS image, it: Calculates hash of the image. Uses public key to uncover hash value from included signature. Compares the calculated and uncovered hashes for a match. The \"secure bootloader\" should be placed in protected memory on a given microcontroller. The Mynewt bootloader comprises two packages: The bootutil library (boot/bootutil) The boot application (apps/boot) The Mynewt code is thus structured so that the generic bootutil library performs most of the functions of a boot loader. The final step of actually jumping to the main image is kept out of the bootutil library. This last step should instead be implemented in an architecture-specific project. Boot loader functionality is separated in this manner for the following two reasons: By keeping architecture-dependent code separate, the bootutil library can be reused among several boot loaders. By excluding the last boot step from the library, the bootloader can be unit tested since a library can be unit tested but an applicant can't. Limitations The boot loader currently only supports images with the following characteristics: Built to run from flash. Build to run from a fixed location (i.e., position-independent). Image Format The following definitions describe the image header format. #define IMAGE_MAGIC 0x96f3b83c #define IMAGE_MAGIC_NONE 0xffffffff struct image_version { uint8_t iv_major ; uint8_t iv_minor ; uint16_t iv_revision ; uint32_t iv_build_num ; }; /** Image header. All fields are in little endian byte order. */ struct image_header { uint32_t ih_magic ; uint16_t ih_tlv_size ; /* Trailing TLVs */ uint8_t ih_key_id ; uint8_t _pad1 ; uint16_t ih_hdr_size ; uint16_t _pad2 ; uint32_t ih_img_size ; /* Does not include header. */ uint32_t ih_flags ; struct image_version ih_ver ; uint32_t _pad3 ; }; The ih_hdr_size field indicates the length of the header, and therefore the offset of the image itself. This field provides for backwards compatibility in case of changes to the format of the image header. The following are the image header flags available. #define IMAGE_F_PIC 0x00000001 #define IMAGE_F_SHA256 0x00000002 /* Image contains hash TLV */ #define IMAGE_F_PKCS15_RSA2048_SHA256 0x00000004 /* PKCS15 w/RSA and SHA */ #define IMAGE_F_ECDSA224_SHA256 0x00000008 /* ECDSA256 over SHA256 */ #define IMAGE_F_NON_BOOTABLE 0x00000010 #define IMAGE_HEADER_SIZE 32 Optional type-length-value records (TLVs) containing image metadata are placed after the end of the image. For example, security data gets added as a footer at the end of the image. /** Image trailer TLV format. All fields in little endian. */ struct image_tlv { uint8_t it_type ; /* IMAGE_TLV_[...]. */ uint8_t _pad ; uint16_t it_len /* Data length (not including TLV header). */ }; /* * Image trailer TLV types. */ #define IMAGE_TLV_SHA256 1 /* SHA256 of image hdr and body */ #define IMAGE_TLV_RSA2048 2 /* RSA2048 of hash output */ #define IMAGE_TLV_ECDSA224 3 /* ECDSA of hash output */ Flash Map A Mynewt device's flash is partitioned according to its flash map . At a high level, the flash map maps numeric IDs to flash areas . A flash area is a region of disk with the following properties: An area can be fully erased without affecting any other areas. A write to one area does not restrict writes to other areas. The boot loader uses the following flash areas: #define FLASH_AREA_BOOTLOADER 0 #define FLASH_AREA_IMAGE_0 1 #define FLASH_AREA_IMAGE_1 2 #define FLASH_AREA_IMAGE_SCRATCH 3 Image Slots A portion of the flash memory is partitioned into two image slots: a primary slot and a secondary slot. The boot loader will only run an image from the primary slot, so images must be built such that they can run from that fixed location in flash. If the boot loader needs to run the image resident in the secondary slot, it must swap the two images in flash prior to booting. In addition to the two image slots, the boot loader requires a scratch area to allow for reliable image swapping. Boot States Logically, you can think of a pair of flags associated with each image slot: pending and confirmed. On startup, the boot loader determines the state of the device by inspecting each pair of flags. These flags have the following meanings: pending: image gets tested on next reboot; absent subsequent confirm command, revert to original image on second reboot. confirmed: always use image unless excluded by a test image. In English, when the user wants to run the secondary image, they set the pending flag for the second slot and reboot the device. On startup, the boot loader will swap the two images in flash, clear the secondary slot's pending flag, and run the newly-copied image in slot 0. This is a temporary state; if the device reboots again, the boot loader swaps the images back to their original slots and boots into the original image. If the user doesn't want to revert to the original state, they can make the current state permanent by setting the confirmed flag in slot 0. Switching to an alternate image is a two-step process (set + confirm) to prevent a device from becoming \"bricked\" by bad firmware. If the device crashes immediately upon booting the second image, the boot loader reverts to the working image, rather than repeatedly rebooting into the bad image. The following set of tables illustrate the three possible states that the device can be in: | slot-0 | slot-1 | ---------------+--------+--------| pending | | | confirmed | X | | ---------------+--------+--------' Image 0 confirmed; | No change on reboot | ---------------------------------' | slot-0 | slot-1 | ---------------+--------+--------| pending | | X | confirmed | X | | ---------------+--------+--------' Image 0 confirmed; | Test image 1 on next reboot | ---------------------------------' | slot-0 | slot-1 | ---------------+--------+--------| pending | | | confirmed | | X | ---------------+--------+--------' Testing image 0; | Revert to image 1 on next reboot | ---------------------------------' Boot Vector At startup, the boot loader determines which of the above three boot states a device is in by inspecting the boot vector. The boot vector consists of two records (called \"image trailers\"), one written at the end of each image slot. An image trailer has the following structure: 0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ ~ MAGIC (16 octets) ~ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ ~ ~ ~ Swap status (128 * min-write-size * 3) ~ ~ ~ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Copy done | 0xff padding (up to min-write-sz - 1) ~ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Image OK | 0xff padding (up to min-write-sz - 1) ~ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ These records are at the end of each image slot. The offset immediately following such a record represents the start of the next flash area. Note: min-write-size is a property of the flash hardware. If the hardware allows individual bytes to be written at arbitrary addresses, then min-write-size is 1. If the hardware only allows writes at even addresses, then min-write-size is 2, and so on. The fields are defined as follows: MAGIC: The following 16 bytes, written in host-byte-order: const uint32_t boot_img_magic[4] = { 0xf395c277, 0x7fefd260, 0x0f505235, 0x8079b62c, }; Swap status: A series of single-byte records. Each record corresponds to a flash sector in an image slot. A swap status byte indicate the location of the corresponding sector data. During an image swap, image data is moved one sector at a time. The swap status is necessary for resuming a swap operation if the device rebooted before a swap operation completed. Copy done: A single byte indicating whether the image in this slot is complete ( 0x01=done, 0xff=not done ). Image OK: A single byte indicating whether the image in this slot has been confirmed as good by the user ( 0x01=confirmed; 0xff=not confirmed ). The boot vector records are structured around the limitations imposed by flash hardware. As a consequence, they do not have a very intuitive design, and it is difficult to get a sense of the state of the device just by looking at the boot vector. It is better to map all the possible vector states to the swap types (None, Test, Revert) via a set of tables. These tables are reproduced below. In these tables, the \"pending\" and \"confirmed\" flags are shown for illustrative purposes; they are not actually present in the boot vector. State I | slot-0 | slot-1 | -----------------+--------+--------| magic | Unset | Unset | image-ok | Any | N/A | -----------------+--------+--------' pending | | | confirmed | X | | -----------------+--------+--------' swap: none | -----------------------------------' State II | slot-0 | slot-1 | -----------------+--------+--------| magic | Any | Good | image-ok | Any | N/A | -----------------+--------+--------' pending | | X | confirmed | X | | -----------------+--------+--------' swap: test | -----------------------------------' State III | slot-0 | slot-1 | -----------------+--------+--------| magic | Good | Unset | image-ok | 0xff | N/A | -----------------+--------+--------' pending | | | confirmed | | X | -----------------+--------+--------' swap: revert (test image running) | -----------------------------------' State IV | slot-0 | slot-1 | -----------------+--------+--------| magic | Good | Unset | image-ok | 0x01 | N/A | -----------------+--------+--------' pending | | | confirmed | X | | -----------------+--------+--------' swap: none (confirmed test image) | -----------------------------------' High-level Operation With the terms defined, we can now explore the boot loader's operation. First, a high-level overview of the boot process is presented. Then, the following sections describe each step of the process in more detail. Procedure: A. Inspect swap status region; is an interrupted swap is being resumed? Yes: Complete the partial swap operation; skip to step C. No: Proceed to step B. B. Inspect boot vector; is a swap requested? Yes. 1. Is the requested image valid (integrity and security check)? Yes. a. Perform swap operation. b. Persist completion of swap procedure to boot vector. c. Proceed to step C. No. a. Erase invalid image. b. Persist failure of swap procedure to boot vector. c. Proceed to step C. No: Proceed to step C. C. Boot into image in slot 0. Image Swapping The boot loader swaps the contents of the two image slots for two reasons: User has issued an \"image test\" operation; the image in slot-1 should be run once (state II). Test image rebooted without being confirmed; the boot loader should revert to the original image currently in slot-1 (state III). If the boot vector indicates that the image in the secondary slot should be run, the boot loader needs to copy it to the primary slot. The image currently in the primary slot also needs to be retained in flash so that it can be used later. Furthermore, both images need to be recoverable if the boot loader resets in the middle of the swap operation. The two images are swapped according to the following procedure: 1. Determine how many flash sectors each image slot consists of. This number must be the same for both slots. 2. Iterate the list of sector indices in descending order (i.e., starting with the greatest index); current element = \"index\". b. Erase scratch area. c. Copy slot0[index] to scratch area. d. Write updated swap status (i). e. Erase slot1[index] f. Copy slot0[index] to slot1[index] - If these are the last sectors (i.e., first swap being perfomed), copy the full sector *except* the image trailer. - Else, copy entire sector contents. g. Write updated swap status (ii). h. Erase slot0[index]. i. Copy scratch area slot0[index]. j. Write updated swap status (iii). 3. Persist completion of swap procedure to slot 0 image trailer. The additional caveats in step 2f are necessary so that the slot 1 image trailer can be written by the user at a later time. With the image trailer unwritten, the user can test the image in slot 1 (i.e., transition to state II). The particulars of step 3 vary depending on whether an image is being tested or reverted: * test: o Write slot0.copy_done = 1 (should now be in state III) * revert: o Write slot0.magic = BOOT_MAGIC o Write slot0.copy_done = 1 o Write slot0.image_ok = 1 (should now be in state IV) Swap Status The swap status region allows the boot loader to recover in case it restarts in the middle of an image swap operation. The swap status region consists of a series of single-byte records. These records are written independently, and therefore must be padded according to the minimum write size imposed by the flash hardware. In the below figure, a min-write-size of 1 is assumed for simplicity. The structure of the swap status region is illustrated below. In this figure, a min-write-size of 1 is assumed for simplicity. 0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |sec127,state 0 |sec127,state 1 |sec127,state 2 |sec126,state 0 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |sec126,state 1 |sec126,state 2 |sec125,state 0 |sec125,state 1 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |sec125,state 2 | | +-+-+-+-+-+-+-+-+ + ~ ~ ~ [Records for indices 124 through 1 ~ ~ ~ ~ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ ~ |sec000,state 0 |sec000,state 1 |sec000,state 2 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ And now, in English... Each image slot is partitioned into a sequence of flash sectors. If we were to enumerate the sectors in a single slot, starting at 0, we would have a list of sector indices. Since there are two image slots, each sector index would correspond to a pair of sectors. For example, sector index 0 corresponds to the first sector in slot 0 and the first sector in slot 1. Furthermore, we impose a limit of 128 indices. If an image slot consists of more than 128 sectors, the flash layout is not compatible with this boot loader. Finally, reverse the list of indices such that the list starts with index 127 and ends with 0. The swap status region is a representation of this reversed list. During a swap operation, each sector index transitions through four separate states: 0. slot 0: image 0, slot 1: image 1, scratch: N/A 1. slot 0: image 0, slot 1: N/A, scratch: image 1 (1->s, erase 1) 2. slot 0: N/A, slot 1: image 0, scratch: image 1 (0->1, erase 0) 3. slot 0: image 1, slot 1: image 0, scratch: N/A (s->0) Each time a sector index transitions to a new state, the boot loader writes a record to the swap status region. Logically, the boot loader only needs one record per sector index to keep track of the current swap state. However, due to limitations imposed by flash hardware, a record cannot be overwritten when an index's state changes. To solve this problem, the boot loader uses three records per sector index rather than just one. Each sector-state pair is represented as a set of three records. The record values map to the above four states as follows | rec0 | rec1 | rec2 --------+------+------+------ state 0 | 0xff | 0xff | 0xff state 1 | 0x01 | 0xff | 0xff state 2 | 0x01 | 0x02 | 0xff state 3 | 0x01 | 0x02 | 0x03 The swap status region can accommodate 128 sector indices. Hence, the size of the region, in bytes, is 128 * min-write-size * 3 . The number 128 is chosen somewhat arbitrarily and will likely be made configurable. The only requirement for the index count is that is is great enough to account for a maximum-sized image (i.e., at least as great as the total sector count in an image slot). If a device's image slots use less than 128 sectors, the first record that gets written will be somewhere in the middle of the region. For example, if a slot uses 64 sectors, the first sector index that gets swapped is 63, which corresponds to the exact halfway point within the region. Reset Recovery If the boot loader resets in the middle of a swap operation, the two images may be discontiguous in flash. Bootutil recovers from this condition by using the boot vector to determine how the image parts are distributed in flash. The first step is determine where the relevant swap status region is located. Because this region is embedded within the image slots, its location in flash changes during a swap operation. The below set of tables map boot vector contents to swap status location. In these tables, the \"source\" field indicates where the swap status region is located. | slot-0 | scratch | ----------+------------+------------| magic | Good | Any | copy-done | 0x01 | N/A | ----------+------------+------------' source: none | ------------------------------------' | slot-0 | scratch | ----------+------------+------------| magic | Good | Any | copy-done | 0xff | N/A | ----------+------------+------------' source: slot 0 | ------------------------------------' | slot-0 | scratch | ----------+------------+------------| magic | Any | Good | copy-done | Any | N/A | ----------+------------+------------' source: scratch | ------------------------------------' | slot-0 | scratch | ----------+------------+------------| magic | Unset | Any | copy-done | 0xff | N/A | ----------+------------+------------| source: varies | ------------------------------------+------------------------------+ This represents one of two cases: | o No swaps ever (no status to read, so no harm in checking). | o Mid-revert; status in slot 0. | -------------------------------------------------------------------' If the swap status region indicates that the images are not contiguous, bootutil completes the swap operation that was in progress when the system was reset. In other words, it applies the procedure defined in the previous section, moving image 1 into slot 0 and image 0 into slot 1. If the boot status file indicates that an image part is present in the scratch area, this part is copied into the correct location by starting at step e or step h in the area-swap procedure, depending on whether the part belongs to image 0 or image 1. After the swap operation has been completed, the boot loader proceeds as though it had just been started. Integrity Check An image is checked for integrity immediately before it gets copied into the primary slot. If the boot loader doesn't perform an image swap, then it doesn't perform an integrity check. During the integrity check, the boot loader verifies the following aspects of an image: 32-bit magic number must be correct (0x96f3b83c). Image must contain a SHA256 TLV. Calculated SHA256 must matche SHA256 TLV contents. Image may contain a signature TLV. If it does, its contents must be verifiable using a key embedded in the boot loader. Image Signing and Verification As indicated above, the final step of the integrity check is signature verification. The boot loader can have one or more public keys embedded in it at build time. During signature verification, the boot loader verifies that an image was signed with a private key that corresponds to one of its public keys. The image signature TLV indicates the index of the key that is has been signed with. The boot loader uses this index to identify the corresponding public key. For information on embedding public keys in the boot loader, as well as producing signed images, see: boot/bootutil/signed_images.md","title":"toc"},{"location":"os/modules/bootloader/bootloader/#bootloader","text":"The \"bootloader\" is the code that loads the Mynewt OS image into memory and conducts some checks before allowing the OS to be run. It manages images for the embedded system and upgrades of those images using protocols over various interfaces (e.g. serial, BLE, etc.). Typically, systems with bootloaders have at least two program images coexisting on the same microcontroller, and hence must include branch code that performs a check to see if an attempt to update software is already underway and manage the progress of the process. The bootloader in the Apache Mynewt project verifies the cryptographic signature of the firmware image before running it. It maintains a detailed status log for each stage of the boot process. For verification of the authenticity of the OS image, it: Calculates hash of the image. Uses public key to uncover hash value from included signature. Compares the calculated and uncovered hashes for a match. The \"secure bootloader\" should be placed in protected memory on a given microcontroller. The Mynewt bootloader comprises two packages: The bootutil library (boot/bootutil) The boot application (apps/boot) The Mynewt code is thus structured so that the generic bootutil library performs most of the functions of a boot loader. The final step of actually jumping to the main image is kept out of the bootutil library. This last step should instead be implemented in an architecture-specific project. Boot loader functionality is separated in this manner for the following two reasons: By keeping architecture-dependent code separate, the bootutil library can be reused among several boot loaders. By excluding the last boot step from the library, the bootloader can be unit tested since a library can be unit tested but an applicant can't.","title":"Bootloader"},{"location":"os/modules/bootloader/bootloader/#limitations","text":"The boot loader currently only supports images with the following characteristics: Built to run from flash. Build to run from a fixed location (i.e., position-independent).","title":"Limitations"},{"location":"os/modules/bootloader/bootloader/#image-format","text":"The following definitions describe the image header format. #define IMAGE_MAGIC 0x96f3b83c #define IMAGE_MAGIC_NONE 0xffffffff struct image_version { uint8_t iv_major ; uint8_t iv_minor ; uint16_t iv_revision ; uint32_t iv_build_num ; }; /** Image header. All fields are in little endian byte order. */ struct image_header { uint32_t ih_magic ; uint16_t ih_tlv_size ; /* Trailing TLVs */ uint8_t ih_key_id ; uint8_t _pad1 ; uint16_t ih_hdr_size ; uint16_t _pad2 ; uint32_t ih_img_size ; /* Does not include header. */ uint32_t ih_flags ; struct image_version ih_ver ; uint32_t _pad3 ; }; The ih_hdr_size field indicates the length of the header, and therefore the offset of the image itself. This field provides for backwards compatibility in case of changes to the format of the image header. The following are the image header flags available. #define IMAGE_F_PIC 0x00000001 #define IMAGE_F_SHA256 0x00000002 /* Image contains hash TLV */ #define IMAGE_F_PKCS15_RSA2048_SHA256 0x00000004 /* PKCS15 w/RSA and SHA */ #define IMAGE_F_ECDSA224_SHA256 0x00000008 /* ECDSA256 over SHA256 */ #define IMAGE_F_NON_BOOTABLE 0x00000010 #define IMAGE_HEADER_SIZE 32 Optional type-length-value records (TLVs) containing image metadata are placed after the end of the image. For example, security data gets added as a footer at the end of the image. /** Image trailer TLV format. All fields in little endian. */ struct image_tlv { uint8_t it_type ; /* IMAGE_TLV_[...]. */ uint8_t _pad ; uint16_t it_len /* Data length (not including TLV header). */ }; /* * Image trailer TLV types. */ #define IMAGE_TLV_SHA256 1 /* SHA256 of image hdr and body */ #define IMAGE_TLV_RSA2048 2 /* RSA2048 of hash output */ #define IMAGE_TLV_ECDSA224 3 /* ECDSA of hash output */","title":"Image Format"},{"location":"os/modules/bootloader/bootloader/#flash-map","text":"A Mynewt device's flash is partitioned according to its flash map . At a high level, the flash map maps numeric IDs to flash areas . A flash area is a region of disk with the following properties: An area can be fully erased without affecting any other areas. A write to one area does not restrict writes to other areas. The boot loader uses the following flash areas: #define FLASH_AREA_BOOTLOADER 0 #define FLASH_AREA_IMAGE_0 1 #define FLASH_AREA_IMAGE_1 2 #define FLASH_AREA_IMAGE_SCRATCH 3","title":"Flash Map"},{"location":"os/modules/bootloader/bootloader/#image-slots","text":"A portion of the flash memory is partitioned into two image slots: a primary slot and a secondary slot. The boot loader will only run an image from the primary slot, so images must be built such that they can run from that fixed location in flash. If the boot loader needs to run the image resident in the secondary slot, it must swap the two images in flash prior to booting. In addition to the two image slots, the boot loader requires a scratch area to allow for reliable image swapping.","title":"Image Slots"},{"location":"os/modules/bootloader/bootloader/#boot-states","text":"Logically, you can think of a pair of flags associated with each image slot: pending and confirmed. On startup, the boot loader determines the state of the device by inspecting each pair of flags. These flags have the following meanings: pending: image gets tested on next reboot; absent subsequent confirm command, revert to original image on second reboot. confirmed: always use image unless excluded by a test image. In English, when the user wants to run the secondary image, they set the pending flag for the second slot and reboot the device. On startup, the boot loader will swap the two images in flash, clear the secondary slot's pending flag, and run the newly-copied image in slot 0. This is a temporary state; if the device reboots again, the boot loader swaps the images back to their original slots and boots into the original image. If the user doesn't want to revert to the original state, they can make the current state permanent by setting the confirmed flag in slot 0. Switching to an alternate image is a two-step process (set + confirm) to prevent a device from becoming \"bricked\" by bad firmware. If the device crashes immediately upon booting the second image, the boot loader reverts to the working image, rather than repeatedly rebooting into the bad image. The following set of tables illustrate the three possible states that the device can be in: | slot-0 | slot-1 | ---------------+--------+--------| pending | | | confirmed | X | | ---------------+--------+--------' Image 0 confirmed; | No change on reboot | ---------------------------------' | slot-0 | slot-1 | ---------------+--------+--------| pending | | X | confirmed | X | | ---------------+--------+--------' Image 0 confirmed; | Test image 1 on next reboot | ---------------------------------' | slot-0 | slot-1 | ---------------+--------+--------| pending | | | confirmed | | X | ---------------+--------+--------' Testing image 0; | Revert to image 1 on next reboot | ---------------------------------'","title":"Boot States"},{"location":"os/modules/bootloader/bootloader/#boot-vector","text":"At startup, the boot loader determines which of the above three boot states a device is in by inspecting the boot vector. The boot vector consists of two records (called \"image trailers\"), one written at the end of each image slot. An image trailer has the following structure: 0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ ~ MAGIC (16 octets) ~ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ ~ ~ ~ Swap status (128 * min-write-size * 3) ~ ~ ~ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Copy done | 0xff padding (up to min-write-sz - 1) ~ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Image OK | 0xff padding (up to min-write-sz - 1) ~ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ These records are at the end of each image slot. The offset immediately following such a record represents the start of the next flash area. Note: min-write-size is a property of the flash hardware. If the hardware allows individual bytes to be written at arbitrary addresses, then min-write-size is 1. If the hardware only allows writes at even addresses, then min-write-size is 2, and so on. The fields are defined as follows: MAGIC: The following 16 bytes, written in host-byte-order: const uint32_t boot_img_magic[4] = { 0xf395c277, 0x7fefd260, 0x0f505235, 0x8079b62c, }; Swap status: A series of single-byte records. Each record corresponds to a flash sector in an image slot. A swap status byte indicate the location of the corresponding sector data. During an image swap, image data is moved one sector at a time. The swap status is necessary for resuming a swap operation if the device rebooted before a swap operation completed. Copy done: A single byte indicating whether the image in this slot is complete ( 0x01=done, 0xff=not done ). Image OK: A single byte indicating whether the image in this slot has been confirmed as good by the user ( 0x01=confirmed; 0xff=not confirmed ). The boot vector records are structured around the limitations imposed by flash hardware. As a consequence, they do not have a very intuitive design, and it is difficult to get a sense of the state of the device just by looking at the boot vector. It is better to map all the possible vector states to the swap types (None, Test, Revert) via a set of tables. These tables are reproduced below. In these tables, the \"pending\" and \"confirmed\" flags are shown for illustrative purposes; they are not actually present in the boot vector. State I | slot-0 | slot-1 | -----------------+--------+--------| magic | Unset | Unset | image-ok | Any | N/A | -----------------+--------+--------' pending | | | confirmed | X | | -----------------+--------+--------' swap: none | -----------------------------------' State II | slot-0 | slot-1 | -----------------+--------+--------| magic | Any | Good | image-ok | Any | N/A | -----------------+--------+--------' pending | | X | confirmed | X | | -----------------+--------+--------' swap: test | -----------------------------------' State III | slot-0 | slot-1 | -----------------+--------+--------| magic | Good | Unset | image-ok | 0xff | N/A | -----------------+--------+--------' pending | | | confirmed | | X | -----------------+--------+--------' swap: revert (test image running) | -----------------------------------' State IV | slot-0 | slot-1 | -----------------+--------+--------| magic | Good | Unset | image-ok | 0x01 | N/A | -----------------+--------+--------' pending | | | confirmed | X | | -----------------+--------+--------' swap: none (confirmed test image) | -----------------------------------'","title":"Boot Vector"},{"location":"os/modules/bootloader/bootloader/#high-level-operation","text":"With the terms defined, we can now explore the boot loader's operation. First, a high-level overview of the boot process is presented. Then, the following sections describe each step of the process in more detail. Procedure: A. Inspect swap status region; is an interrupted swap is being resumed? Yes: Complete the partial swap operation; skip to step C. No: Proceed to step B. B. Inspect boot vector; is a swap requested? Yes. 1. Is the requested image valid (integrity and security check)? Yes. a. Perform swap operation. b. Persist completion of swap procedure to boot vector. c. Proceed to step C. No. a. Erase invalid image. b. Persist failure of swap procedure to boot vector. c. Proceed to step C. No: Proceed to step C. C. Boot into image in slot 0.","title":"High-level Operation"},{"location":"os/modules/bootloader/bootloader/#image-swapping","text":"The boot loader swaps the contents of the two image slots for two reasons: User has issued an \"image test\" operation; the image in slot-1 should be run once (state II). Test image rebooted without being confirmed; the boot loader should revert to the original image currently in slot-1 (state III). If the boot vector indicates that the image in the secondary slot should be run, the boot loader needs to copy it to the primary slot. The image currently in the primary slot also needs to be retained in flash so that it can be used later. Furthermore, both images need to be recoverable if the boot loader resets in the middle of the swap operation. The two images are swapped according to the following procedure: 1. Determine how many flash sectors each image slot consists of. This number must be the same for both slots. 2. Iterate the list of sector indices in descending order (i.e., starting with the greatest index); current element = \"index\". b. Erase scratch area. c. Copy slot0[index] to scratch area. d. Write updated swap status (i). e. Erase slot1[index] f. Copy slot0[index] to slot1[index] - If these are the last sectors (i.e., first swap being perfomed), copy the full sector *except* the image trailer. - Else, copy entire sector contents. g. Write updated swap status (ii). h. Erase slot0[index]. i. Copy scratch area slot0[index]. j. Write updated swap status (iii). 3. Persist completion of swap procedure to slot 0 image trailer. The additional caveats in step 2f are necessary so that the slot 1 image trailer can be written by the user at a later time. With the image trailer unwritten, the user can test the image in slot 1 (i.e., transition to state II). The particulars of step 3 vary depending on whether an image is being tested or reverted: * test: o Write slot0.copy_done = 1 (should now be in state III) * revert: o Write slot0.magic = BOOT_MAGIC o Write slot0.copy_done = 1 o Write slot0.image_ok = 1 (should now be in state IV)","title":"Image Swapping"},{"location":"os/modules/bootloader/bootloader/#swap-status","text":"The swap status region allows the boot loader to recover in case it restarts in the middle of an image swap operation. The swap status region consists of a series of single-byte records. These records are written independently, and therefore must be padded according to the minimum write size imposed by the flash hardware. In the below figure, a min-write-size of 1 is assumed for simplicity. The structure of the swap status region is illustrated below. In this figure, a min-write-size of 1 is assumed for simplicity. 0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |sec127,state 0 |sec127,state 1 |sec127,state 2 |sec126,state 0 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |sec126,state 1 |sec126,state 2 |sec125,state 0 |sec125,state 1 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |sec125,state 2 | | +-+-+-+-+-+-+-+-+ + ~ ~ ~ [Records for indices 124 through 1 ~ ~ ~ ~ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ ~ |sec000,state 0 |sec000,state 1 |sec000,state 2 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ And now, in English... Each image slot is partitioned into a sequence of flash sectors. If we were to enumerate the sectors in a single slot, starting at 0, we would have a list of sector indices. Since there are two image slots, each sector index would correspond to a pair of sectors. For example, sector index 0 corresponds to the first sector in slot 0 and the first sector in slot 1. Furthermore, we impose a limit of 128 indices. If an image slot consists of more than 128 sectors, the flash layout is not compatible with this boot loader. Finally, reverse the list of indices such that the list starts with index 127 and ends with 0. The swap status region is a representation of this reversed list. During a swap operation, each sector index transitions through four separate states: 0. slot 0: image 0, slot 1: image 1, scratch: N/A 1. slot 0: image 0, slot 1: N/A, scratch: image 1 (1->s, erase 1) 2. slot 0: N/A, slot 1: image 0, scratch: image 1 (0->1, erase 0) 3. slot 0: image 1, slot 1: image 0, scratch: N/A (s->0) Each time a sector index transitions to a new state, the boot loader writes a record to the swap status region. Logically, the boot loader only needs one record per sector index to keep track of the current swap state. However, due to limitations imposed by flash hardware, a record cannot be overwritten when an index's state changes. To solve this problem, the boot loader uses three records per sector index rather than just one. Each sector-state pair is represented as a set of three records. The record values map to the above four states as follows | rec0 | rec1 | rec2 --------+------+------+------ state 0 | 0xff | 0xff | 0xff state 1 | 0x01 | 0xff | 0xff state 2 | 0x01 | 0x02 | 0xff state 3 | 0x01 | 0x02 | 0x03 The swap status region can accommodate 128 sector indices. Hence, the size of the region, in bytes, is 128 * min-write-size * 3 . The number 128 is chosen somewhat arbitrarily and will likely be made configurable. The only requirement for the index count is that is is great enough to account for a maximum-sized image (i.e., at least as great as the total sector count in an image slot). If a device's image slots use less than 128 sectors, the first record that gets written will be somewhere in the middle of the region. For example, if a slot uses 64 sectors, the first sector index that gets swapped is 63, which corresponds to the exact halfway point within the region.","title":"Swap Status"},{"location":"os/modules/bootloader/bootloader/#reset-recovery","text":"If the boot loader resets in the middle of a swap operation, the two images may be discontiguous in flash. Bootutil recovers from this condition by using the boot vector to determine how the image parts are distributed in flash. The first step is determine where the relevant swap status region is located. Because this region is embedded within the image slots, its location in flash changes during a swap operation. The below set of tables map boot vector contents to swap status location. In these tables, the \"source\" field indicates where the swap status region is located. | slot-0 | scratch | ----------+------------+------------| magic | Good | Any | copy-done | 0x01 | N/A | ----------+------------+------------' source: none | ------------------------------------' | slot-0 | scratch | ----------+------------+------------| magic | Good | Any | copy-done | 0xff | N/A | ----------+------------+------------' source: slot 0 | ------------------------------------' | slot-0 | scratch | ----------+------------+------------| magic | Any | Good | copy-done | Any | N/A | ----------+------------+------------' source: scratch | ------------------------------------' | slot-0 | scratch | ----------+------------+------------| magic | Unset | Any | copy-done | 0xff | N/A | ----------+------------+------------| source: varies | ------------------------------------+------------------------------+ This represents one of two cases: | o No swaps ever (no status to read, so no harm in checking). | o Mid-revert; status in slot 0. | -------------------------------------------------------------------' If the swap status region indicates that the images are not contiguous, bootutil completes the swap operation that was in progress when the system was reset. In other words, it applies the procedure defined in the previous section, moving image 1 into slot 0 and image 0 into slot 1. If the boot status file indicates that an image part is present in the scratch area, this part is copied into the correct location by starting at step e or step h in the area-swap procedure, depending on whether the part belongs to image 0 or image 1. After the swap operation has been completed, the boot loader proceeds as though it had just been started.","title":"Reset Recovery"},{"location":"os/modules/bootloader/bootloader/#integrity-check","text":"An image is checked for integrity immediately before it gets copied into the primary slot. If the boot loader doesn't perform an image swap, then it doesn't perform an integrity check. During the integrity check, the boot loader verifies the following aspects of an image: 32-bit magic number must be correct (0x96f3b83c). Image must contain a SHA256 TLV. Calculated SHA256 must matche SHA256 TLV contents. Image may contain a signature TLV. If it does, its contents must be verifiable using a key embedded in the boot loader.","title":"Integrity Check"},{"location":"os/modules/bootloader/bootloader/#image-signing-and-verification","text":"As indicated above, the final step of the integrity check is signature verification. The boot loader can have one or more public keys embedded in it at build time. During signature verification, the boot loader verifies that an image was signed with a private key that corresponds to one of its public keys. The image signature TLV indicates the index of the key that is has been signed with. The boot loader uses this index to identify the corresponding public key. For information on embedding public keys in the boot loader, as well as producing signed images, see: boot/bootutil/signed_images.md","title":"Image Signing and Verification"},{"location":"os/modules/console/console/","text":"Console The console is an operating system window where users interact with the OS subsystems or a console application. A user typically inputs text from a keyboard and reads the OS output text on a computer monitor. The text are sent as a sequence of characters between the user and the OS. Support is currently available for console access via the serial port on the hardware board. Description In the Mynewt OS, the console library comes in three versions: The sys/console/full package implements the complete console functionality and API. The sys/console/stub package implements stubs for the API. The sys/console/minimal package implements minimal console functionality of reading from and writing to console. It implements the console_read() and console_write() functions and stubs for all the other console functions. All the packages export the console API, and any package that uses the console API must list console as a requirement its pkg.yml file: pkg.name: sys/shell pkg.deps: - kernel/os - encoding/base64 - time/datetime - util/crc pkg.req_apis: - console The project pkg.yml file also specifies the version of the console package to use. Using the Full Console Package A project that requires the full console capability must list the sys/console/full package as a dependency in its pkg.yml file. An example is the slinky application. It requires the full console capability and has the following pkg.yml file: pkg.name: apps/slinky pkg.deps: - test/flash_test - mgmt/imgmgr - mgmt/newtmgr - mgmt/newtmgr/transport/nmgr_shell - kernel/os - boot/bootutil - sys/shell - sys/console/full ... - sys/id Using the Stub Console Package A project that uses console stub API must list the sys/console/stub package as a dependency in its pkg.yml file. Examples of when a project would use the console stubs might be: A project may not have a physical console (e.g. a UART port to connect a terminal to) but may have a dependency on a package that has console capability. A bootloader project where we want to keep the size of the image small. It includes the kernel/os package that can print out messages on a console (e.g. if there is a hard fault). However, we do not want to use any console I/O capability in this particular bootloader project to keep the size small. The project would use the console stub API and has the following pkg.yml file: pkg.name: apps/boot pkg.deps: - boot/bootutil - kernel/os - sys/console/stub Using the Minimal Console Package There might be projects that need to read and write data on a serial connection but do not need the full console capability. An example might be a project that supports serial image upgrade but does not need full newtmgr capability. The project would use the console minimal API and has the following pkg.yml file: pkg.name: apps/boot pkg.type: app pkg.description: Boot loader application. pkg.author: \"Apache Mynewt <dev@mynewt.incubator.apache.org>\" pkg.homepage: \"http://mynewt.apache.org/\" pkg.keywords: - loader pkg.deps: - boot/bootutil - kernel/os - sys/console/stub pkg.deps.BOOT_SERIAL.OVERWRITE: - sys/console/minimal - boot/boot_serial Console has 2 modes for transmit; blocking mode and non-blocking mode . Usually the non-blocking mode is the active one; the output buffer is drained by getting TX completion interrupts from hardware, and more data is added based on these interrupts. Blocking mode is used when we don't want TX completion interrupts. It is used when system crashes, and we still want to output info related to that crash. Console, by default, echoes everything it receives back. Terminal programs expect this, and is a way for the user to know that the console is connected and responsive. Whether echoing happens or not can be controlled programmatically. The Console also has a prompt that is configurable. It is off by default but can be turned on programmatically. The prompt character can also be changed by the user. Data structures N/A List of Functions The functions available in console are: Function Description console_blocking_mode Calls the console_blocking_tx function to flush the buffered console output (transmit) queue. console_echo Controls whether echoing is on or off for the console. console_init Initialize the console. console_is_init Returns whether console has been initialized or not. console_printf Writes a formatted message instead of raw output to the console. console_read Copies up the to given number of bytes to the input string. console_write Queues characters to console display over serial port.","title":"toc"},{"location":"os/modules/console/console/#console","text":"The console is an operating system window where users interact with the OS subsystems or a console application. A user typically inputs text from a keyboard and reads the OS output text on a computer monitor. The text are sent as a sequence of characters between the user and the OS. Support is currently available for console access via the serial port on the hardware board.","title":"Console"},{"location":"os/modules/console/console/#description","text":"In the Mynewt OS, the console library comes in three versions: The sys/console/full package implements the complete console functionality and API. The sys/console/stub package implements stubs for the API. The sys/console/minimal package implements minimal console functionality of reading from and writing to console. It implements the console_read() and console_write() functions and stubs for all the other console functions. All the packages export the console API, and any package that uses the console API must list console as a requirement its pkg.yml file: pkg.name: sys/shell pkg.deps: - kernel/os - encoding/base64 - time/datetime - util/crc pkg.req_apis: - console The project pkg.yml file also specifies the version of the console package to use.","title":"Description"},{"location":"os/modules/console/console/#using-the-full-console-package","text":"A project that requires the full console capability must list the sys/console/full package as a dependency in its pkg.yml file. An example is the slinky application. It requires the full console capability and has the following pkg.yml file: pkg.name: apps/slinky pkg.deps: - test/flash_test - mgmt/imgmgr - mgmt/newtmgr - mgmt/newtmgr/transport/nmgr_shell - kernel/os - boot/bootutil - sys/shell - sys/console/full ... - sys/id","title":"Using the Full Console Package"},{"location":"os/modules/console/console/#using-the-stub-console-package","text":"A project that uses console stub API must list the sys/console/stub package as a dependency in its pkg.yml file. Examples of when a project would use the console stubs might be: A project may not have a physical console (e.g. a UART port to connect a terminal to) but may have a dependency on a package that has console capability. A bootloader project where we want to keep the size of the image small. It includes the kernel/os package that can print out messages on a console (e.g. if there is a hard fault). However, we do not want to use any console I/O capability in this particular bootloader project to keep the size small. The project would use the console stub API and has the following pkg.yml file: pkg.name: apps/boot pkg.deps: - boot/bootutil - kernel/os - sys/console/stub","title":"Using the Stub Console Package"},{"location":"os/modules/console/console/#using-the-minimal-console-package","text":"There might be projects that need to read and write data on a serial connection but do not need the full console capability. An example might be a project that supports serial image upgrade but does not need full newtmgr capability. The project would use the console minimal API and has the following pkg.yml file: pkg.name: apps/boot pkg.type: app pkg.description: Boot loader application. pkg.author: \"Apache Mynewt <dev@mynewt.incubator.apache.org>\" pkg.homepage: \"http://mynewt.apache.org/\" pkg.keywords: - loader pkg.deps: - boot/bootutil - kernel/os - sys/console/stub pkg.deps.BOOT_SERIAL.OVERWRITE: - sys/console/minimal - boot/boot_serial Console has 2 modes for transmit; blocking mode and non-blocking mode . Usually the non-blocking mode is the active one; the output buffer is drained by getting TX completion interrupts from hardware, and more data is added based on these interrupts. Blocking mode is used when we don't want TX completion interrupts. It is used when system crashes, and we still want to output info related to that crash. Console, by default, echoes everything it receives back. Terminal programs expect this, and is a way for the user to know that the console is connected and responsive. Whether echoing happens or not can be controlled programmatically. The Console also has a prompt that is configurable. It is off by default but can be turned on programmatically. The prompt character can also be changed by the user.","title":"Using the Minimal Console Package"},{"location":"os/modules/console/console/#data-structures","text":"N/A","title":"Data structures"},{"location":"os/modules/console/console/#list-of-functions","text":"The functions available in console are: Function Description console_blocking_mode Calls the console_blocking_tx function to flush the buffered console output (transmit) queue. console_echo Controls whether echoing is on or off for the console. console_init Initialize the console. console_is_init Returns whether console has been initialized or not. console_printf Writes a formatted message instead of raw output to the console. console_read Copies up the to given number of bytes to the input string. console_write Queues characters to console display over serial port.","title":"List of Functions"},{"location":"os/modules/console/console_blocking_mode/","text":"console_blocking_mode void console_blocking_mode ( void ) Calls the console_blocking_tx function to flush the buffered console output (transmit) queue. The function OS_ENTER_CRITICAL() is called to disable interrupts and OS_EXIT_CRITICAL() is called to enable interrupts back again once the buffer is flushed. Arguments None Returned values N/A Example Here is an example of calling console_blocking_mode and printing crash information from an assert to help debug. void _assert_func ( const char *file , int line , const char *func , const char *e ) { int sr ; OS_ENTER_CRITICAL ( sr ); ( void ) sr ; os_die_line = line ; os_die_module = file ; console_blocking_mode (); console_printf ( \"Assert %s; failed in %s:%d\\n\" , e ? e : \"\" , file , line ); system_reset (); }","title":"console_blocking_mode"},{"location":"os/modules/console/console_blocking_mode/#console_blocking_mode","text":"void console_blocking_mode ( void ) Calls the console_blocking_tx function to flush the buffered console output (transmit) queue. The function OS_ENTER_CRITICAL() is called to disable interrupts and OS_EXIT_CRITICAL() is called to enable interrupts back again once the buffer is flushed.","title":" console_blocking_mode "},{"location":"os/modules/console/console_blocking_mode/#arguments","text":"None","title":"Arguments"},{"location":"os/modules/console/console_blocking_mode/#returned-values","text":"N/A","title":"Returned values"},{"location":"os/modules/console/console_blocking_mode/#example","text":"Here is an example of calling console_blocking_mode and printing crash information from an assert to help debug. void _assert_func ( const char *file , int line , const char *func , const char *e ) { int sr ; OS_ENTER_CRITICAL ( sr ); ( void ) sr ; os_die_line = line ; os_die_module = file ; console_blocking_mode (); console_printf ( \"Assert %s; failed in %s:%d\\n\" , e ? e : \"\" , file , line ); system_reset (); }","title":"Example"},{"location":"os/modules/console/console_echo/","text":"console_echo void console_echo ( int on ) Controls whether echoing is on or off for the console. When echoing is on, all characters received are transmitted back. Arguments Arguments Description on 1 turns on echoing, 0 turns it off Returned values None Notes None Example Here is an example where newtmgr protocol handler is controlling whether echoing is on or off. Newtmgr turns echoing off when it is transmitting large chunks of data to a target board. static int nmgr_def_console_echo ( struct nmgr_jbuf *njb ) { int echo_on = 1 ; int rc ; struct json_attr_t attrs [ 3 ] = { [ 0 ] = { . attribute = \"echo\" , . type = t_integer , . addr . integer = &echo_on , . nodefault = 1 }, [ 1 ] = { . attribute = NULL } }; rc = json_read_object ( &njb->njb_buf , attrs ); if ( rc ) { return OS_EINVAL ; } if ( echo_on ) { console_echo ( 1 ); } else { console_echo ( 0 ); } return ( 0 ); }","title":"console_echo"},{"location":"os/modules/console/console_echo/#console_echo","text":"void console_echo ( int on ) Controls whether echoing is on or off for the console. When echoing is on, all characters received are transmitted back.","title":" console_echo "},{"location":"os/modules/console/console_echo/#arguments","text":"Arguments Description on 1 turns on echoing, 0 turns it off","title":"Arguments"},{"location":"os/modules/console/console_echo/#returned-values","text":"None","title":"Returned values"},{"location":"os/modules/console/console_echo/#notes","text":"None","title":"Notes"},{"location":"os/modules/console/console_echo/#example","text":"Here is an example where newtmgr protocol handler is controlling whether echoing is on or off. Newtmgr turns echoing off when it is transmitting large chunks of data to a target board. static int nmgr_def_console_echo ( struct nmgr_jbuf *njb ) { int echo_on = 1 ; int rc ; struct json_attr_t attrs [ 3 ] = { [ 0 ] = { . attribute = \"echo\" , . type = t_integer , . addr . integer = &echo_on , . nodefault = 1 }, [ 1 ] = { . attribute = NULL } }; rc = json_read_object ( &njb->njb_buf , attrs ); if ( rc ) { return OS_EINVAL ; } if ( echo_on ) { console_echo ( 1 ); } else { console_echo ( 0 ); } return ( 0 ); }","title":"Example"},{"location":"os/modules/console/console_init/","text":"console_init int console_init ( console_rx_cb rx_cb ) Initializes the console receive buffer and calls hal funtions hal_uart_init_cbs and hal_uart_config to initialize the serial port connection and configure it (e.g. baud rate, flow control etc.) Caller registers a function pointer of type void (*console_rx_cb)(int full_line) . This function will be called when the console receives either a) full line of data or b) when RX buffer in console is full. Note that this function is most likely getting called from an interrupt context. Arguments Arguments Description rx_cb Function pointer, which gets called when input is received. Returned values Returns 0 on success. Non-zero if HAL UART function calls fail. Example int main ( int argc , char **argv ) { .... /* Init tasks */ shell_task_init ( SHELL_TASK_PRIO , shell_stack , SHELL_TASK_STACK_SIZE , SHELL_MAX_INPUT_LEN ); console_init ( shell_console_rx_cb ); .... }","title":"console_init"},{"location":"os/modules/console/console_init/#console_init","text":"int console_init ( console_rx_cb rx_cb ) Initializes the console receive buffer and calls hal funtions hal_uart_init_cbs and hal_uart_config to initialize the serial port connection and configure it (e.g. baud rate, flow control etc.) Caller registers a function pointer of type void (*console_rx_cb)(int full_line) . This function will be called when the console receives either a) full line of data or b) when RX buffer in console is full. Note that this function is most likely getting called from an interrupt context.","title":" console_init "},{"location":"os/modules/console/console_init/#arguments","text":"Arguments Description rx_cb Function pointer, which gets called when input is received.","title":"Arguments"},{"location":"os/modules/console/console_init/#returned-values","text":"Returns 0 on success. Non-zero if HAL UART function calls fail.","title":"Returned values"},{"location":"os/modules/console/console_init/#example","text":"int main ( int argc , char **argv ) { .... /* Init tasks */ shell_task_init ( SHELL_TASK_PRIO , shell_stack , SHELL_TASK_STACK_SIZE , SHELL_MAX_INPUT_LEN ); console_init ( shell_console_rx_cb ); .... }","title":"Example"},{"location":"os/modules/console/console_is_init/","text":"console_is_init int console_is_init ( void ) Returns whether console has been initialized or not. I.e. whether console_init() has been called yet. Arguments None Returned values Returns 1 if console has been initialized. 0 if not. Example static int log_console_append ( struct log *log , void *buf , int len ) { .... if ( !console_is_init ()) { return ( 0 ); } /* print log entry to console */ .... }","title":"console_is_init"},{"location":"os/modules/console/console_is_init/#console_is_init","text":"int console_is_init ( void ) Returns whether console has been initialized or not. I.e. whether console_init() has been called yet.","title":" console_is_init "},{"location":"os/modules/console/console_is_init/#arguments","text":"None","title":"Arguments"},{"location":"os/modules/console/console_is_init/#returned-values","text":"Returns 1 if console has been initialized. 0 if not.","title":"Returned values"},{"location":"os/modules/console/console_is_init/#example","text":"static int log_console_append ( struct log *log , void *buf , int len ) { .... if ( !console_is_init ()) { return ( 0 ); } /* print log entry to console */ .... }","title":"Example"},{"location":"os/modules/console/console_printf/","text":"console_printf void console_printf ( const char *fmt , ...) Writes a formatted message instead of raw output to the console. It first composes a C string containing the text specified as arguments to the function or containing the elements in the variable argument list passed to it using snprintf or vsnprintf , respectively. It then uses the function console_write to output the formatted data (messages) on the console. Arguments Arguments Description fmt Pointer to C string that contains a format string that follows the same specifications as format in printf. The string is printed to console. ... Depending on the format string, the function may expect either a sequence of additional arguments to be used to replace a format specifier in the format string or a variable arguments list. va_list is a special type defined in in stdarg.h . Returned values None Notes While console_printf , with its well understood formatting options in C, is more convenient and easy on the eyes than the raw output of console_write , the associated code size is considerably larger. Example Example #1: char adv_data_buf [ 32 ]; void task () { char adv_data_buf [ 32 ]; console_printf ( \"%s\" , adv_data_buf ); } Example #2: struct exception_frame { uint32_t r0 ; uint32_t r1 ; struct trap_frame { struct exception_frame *ef ; uint32_t r2 ; uint32_t r3 ; }; void task ( struct trap_frame *tf ) { console_printf ( \" r0:%8.8x r1:%8.8x\" , tf->ef->r0 , tf->ef->r1 ); console_printf ( \" r8:%8.8x r9:%8.8x\" , tf->r2 , tf->r3 ); }","title":"console_printf"},{"location":"os/modules/console/console_printf/#console_printf","text":"void console_printf ( const char *fmt , ...) Writes a formatted message instead of raw output to the console. It first composes a C string containing the text specified as arguments to the function or containing the elements in the variable argument list passed to it using snprintf or vsnprintf , respectively. It then uses the function console_write to output the formatted data (messages) on the console.","title":" console_printf"},{"location":"os/modules/console/console_printf/#arguments","text":"Arguments Description fmt Pointer to C string that contains a format string that follows the same specifications as format in printf. The string is printed to console. ... Depending on the format string, the function may expect either a sequence of additional arguments to be used to replace a format specifier in the format string or a variable arguments list. va_list is a special type defined in in stdarg.h .","title":"Arguments"},{"location":"os/modules/console/console_printf/#returned-values","text":"None","title":"Returned values"},{"location":"os/modules/console/console_printf/#notes","text":"While console_printf , with its well understood formatting options in C, is more convenient and easy on the eyes than the raw output of console_write , the associated code size is considerably larger.","title":"Notes"},{"location":"os/modules/console/console_printf/#example","text":"Example #1: char adv_data_buf [ 32 ]; void task () { char adv_data_buf [ 32 ]; console_printf ( \"%s\" , adv_data_buf ); } Example #2: struct exception_frame { uint32_t r0 ; uint32_t r1 ; struct trap_frame { struct exception_frame *ef ; uint32_t r2 ; uint32_t r3 ; }; void task ( struct trap_frame *tf ) { console_printf ( \" r0:%8.8x r1:%8.8x\" , tf->ef->r0 , tf->ef->r1 ); console_printf ( \" r8:%8.8x r9:%8.8x\" , tf->r2 , tf->r3 ); }","title":"Example"},{"location":"os/modules/console/console_read/","text":"console_read int console_read ( char *str , int cnt , int *newline ) Copies up to cnt bytes of received data to buffer pointed by str . Function tries to break the input into separate lines; once it encounters a newline character, it replaces that with end-of-string and returns. Arguments Arguments Description str Buffer where data is copied to. cnt Maximum number of characters to copy. newline Pointer to an integer variable that is set to 1 when an newline character is received and set to 0 otherwise. Returned values Returns the number of characters copied. 0 if there was no data available, or if the first received character was '\\n'. Example void task1_loop ( void *arg ) { struct os_event *ev ; char rx_msg [ 128 ]; int rx_len ; int newline ; while ( 1 ) { ev = os_eventq_get ( &task1_evq ); assert ( ev ); if ( ev->ev_type == CONS_EV_TYPE ) { rx_len = console_read ( rx_msg , sizeof ( rx_msg ), &newline ); if ( rx_len ) { if ( !strncmp ( rx_msg , \"reset\" , rx_len )) { assert ( 0 ); } } } } }","title":"console_read"},{"location":"os/modules/console/console_read/#console_read","text":"int console_read ( char *str , int cnt , int *newline ) Copies up to cnt bytes of received data to buffer pointed by str . Function tries to break the input into separate lines; once it encounters a newline character, it replaces that with end-of-string and returns.","title":" console_read "},{"location":"os/modules/console/console_read/#arguments","text":"Arguments Description str Buffer where data is copied to. cnt Maximum number of characters to copy. newline Pointer to an integer variable that is set to 1 when an newline character is received and set to 0 otherwise.","title":"Arguments"},{"location":"os/modules/console/console_read/#returned-values","text":"Returns the number of characters copied. 0 if there was no data available, or if the first received character was '\\n'.","title":"Returned values"},{"location":"os/modules/console/console_read/#example","text":"void task1_loop ( void *arg ) { struct os_event *ev ; char rx_msg [ 128 ]; int rx_len ; int newline ; while ( 1 ) { ev = os_eventq_get ( &task1_evq ); assert ( ev ); if ( ev->ev_type == CONS_EV_TYPE ) { rx_len = console_read ( rx_msg , sizeof ( rx_msg ), &newline ); if ( rx_len ) { if ( !strncmp ( rx_msg , \"reset\" , rx_len )) { assert ( 0 ); } } } } }","title":"Example"},{"location":"os/modules/console/console_write/","text":"console_write void console_write ( char *str , int cnt ) Queues characters to console display over serial port. Arguments Arguments Description *str pointer to the character or packet to be transmitted cnt number of characters in str Returned values N/A Example Here is an example of the function being used in an echo command with a newline at the end. static int shell_echo_cmd ( int argc , char **argv ) { int i ; for ( i = 1 ; i < argc ; i++ ) { console_write ( argv [ i ], strlen ( argv [ i ])); console_write ( \" \" , sizeof ( \" \" ) -1 ); } console_write ( \"\\n\" , sizeof ( \"\\n\" ) -1 ); return ( 0 ); }","title":"console_write"},{"location":"os/modules/console/console_write/#console_write","text":"void console_write ( char *str , int cnt ) Queues characters to console display over serial port.","title":" console_write "},{"location":"os/modules/console/console_write/#arguments","text":"Arguments Description *str pointer to the character or packet to be transmitted cnt number of characters in str","title":"Arguments"},{"location":"os/modules/console/console_write/#returned-values","text":"N/A","title":"Returned values"},{"location":"os/modules/console/console_write/#example","text":"Here is an example of the function being used in an echo command with a newline at the end. static int shell_echo_cmd ( int argc , char **argv ) { int i ; for ( i = 1 ; i < argc ; i++ ) { console_write ( argv [ i ], strlen ( argv [ i ])); console_write ( \" \" , sizeof ( \" \" ) -1 ); } console_write ( \"\\n\" , sizeof ( \"\\n\" ) -1 ); return ( 0 ); }","title":"Example"},{"location":"os/modules/devmgmt/customize_newtmgr/","text":"Customizing Newt Manager Usage with mgmt The mgmt package enables you to customize Newt Manager (in either the newtmgr or oicmgr framerwork) to only process the commands that your application uses. The newtmgr commands are divided into management groups. A manager package implements the commands for a group. It implements the handlers that process the commands for the group and registers the handlers with mgmt. When newtmgr or oicmgr receives a newtmgr command, it looks up the handler for the command (by management group id and command id) from mgmt and calls the handler to process the command. The system level management groups are listed in following table: Management Group newtmgr Commands Package MGMT_GROUP_ID_DEFAULT ```echo``` ```taskstats``` ```mpstats``` ```datetime``` ```reset``` mgmt/newtmgr/nmgr_os MGMT_GROUP_ID_IMAGE ```image``` mgmt/imgmgr MGMT_GROUP_ID_STATS ```stat``` sys/stats MGMT_GROUP_ID_CONFIG ```config``` sys/config MGMT_GROUP_ID_LOGS ```log``` sys/log MGMT_GROUP_ID_CRASH ```crash``` test/crash_test MGMT_GROUP_ID_RUNTEST ```run``` test/runtest Both newtmgr and ocimgr process the MGMT_GROUP_ID_DEFAULT commands by default. You can also use mgmt to add user defined management group commands.","title":"Customizing Newt Manager Usage with mgmt"},{"location":"os/modules/devmgmt/customize_newtmgr/#customizing-newt-manager-usage-with-mgmt","text":"The mgmt package enables you to customize Newt Manager (in either the newtmgr or oicmgr framerwork) to only process the commands that your application uses. The newtmgr commands are divided into management groups. A manager package implements the commands for a group. It implements the handlers that process the commands for the group and registers the handlers with mgmt. When newtmgr or oicmgr receives a newtmgr command, it looks up the handler for the command (by management group id and command id) from mgmt and calls the handler to process the command. The system level management groups are listed in following table: Management Group newtmgr Commands Package MGMT_GROUP_ID_DEFAULT ```echo``` ```taskstats``` ```mpstats``` ```datetime``` ```reset``` mgmt/newtmgr/nmgr_os MGMT_GROUP_ID_IMAGE ```image``` mgmt/imgmgr MGMT_GROUP_ID_STATS ```stat``` sys/stats MGMT_GROUP_ID_CONFIG ```config``` sys/config MGMT_GROUP_ID_LOGS ```log``` sys/log MGMT_GROUP_ID_CRASH ```crash``` test/crash_test MGMT_GROUP_ID_RUNTEST ```run``` test/runtest Both newtmgr and ocimgr process the MGMT_GROUP_ID_DEFAULT commands by default. You can also use mgmt to add user defined management group commands.","title":"Customizing Newt Manager Usage with mgmt"},{"location":"os/modules/devmgmt/newtmgr/","text":"Newt Manager Newt Manager is the protocol that enables your Mynewt application to communicate remotely with your device running the Mynewt OS in order to configure, manage, conduct maintenance, and monitor it. The core device management module is called mgmt and offers multiple options for invoking the appropriate newt manager commands for various operations on the device e.g. enabling and collecting logs, configuring and retrieving stats, resetting the device etc. Use the newtmgr package if reduced code footprint is your primary requirement and you do not have interoperability requirements upstream for device information, discovery, and connectivity. Use the oicmgr package if interoperability and standards-based connectivity for device interaction is your primary requirement. This package supports the OIC (Open Interconnect Consortium) Specification 1.1.0 framework from Open Connectivity Foundation (OCF). Invoking Newt Manager commands The diagram below indicates the two options available to the application developer to issue Newt Manager ( newtmgr ) commands on a Mynewt device. The application may leverage the newtmgr framework or the oicmgr framework to call the newtmgr commands. The latter is described in the next chapter. newtmgr The newtmgr framework uses a simple request and response message format to send commands to the device. A message consists of an eight byte header and the message payload. The message header specifies the newtmgr command. The message payload contains the newtmgr request/response data and is encoded in CBOR (Concise Binary Object Representation) format. newtmgr supports BLE and serial connections. The newtmgr framework has a smaller code size and memory footprint than oicmgr but does not support open connectivity.","title":"toc"},{"location":"os/modules/devmgmt/newtmgr/#newt-manager","text":"Newt Manager is the protocol that enables your Mynewt application to communicate remotely with your device running the Mynewt OS in order to configure, manage, conduct maintenance, and monitor it. The core device management module is called mgmt and offers multiple options for invoking the appropriate newt manager commands for various operations on the device e.g. enabling and collecting logs, configuring and retrieving stats, resetting the device etc. Use the newtmgr package if reduced code footprint is your primary requirement and you do not have interoperability requirements upstream for device information, discovery, and connectivity. Use the oicmgr package if interoperability and standards-based connectivity for device interaction is your primary requirement. This package supports the OIC (Open Interconnect Consortium) Specification 1.1.0 framework from Open Connectivity Foundation (OCF).","title":"Newt Manager"},{"location":"os/modules/devmgmt/newtmgr/#invoking-newt-manager-commands","text":"The diagram below indicates the two options available to the application developer to issue Newt Manager ( newtmgr ) commands on a Mynewt device. The application may leverage the newtmgr framework or the oicmgr framework to call the newtmgr commands. The latter is described in the next chapter.","title":"Invoking Newt Manager commands"},{"location":"os/modules/devmgmt/newtmgr/#newtmgr","text":"The newtmgr framework uses a simple request and response message format to send commands to the device. A message consists of an eight byte header and the message payload. The message header specifies the newtmgr command. The message payload contains the newtmgr request/response data and is encoded in CBOR (Concise Binary Object Representation) format. newtmgr supports BLE and serial connections. The newtmgr framework has a smaller code size and memory footprint than oicmgr but does not support open connectivity.","title":"newtmgr"},{"location":"os/modules/devmgmt/oicmgr/","text":"Using the OIC Framework Apache Mynewt includes support for the OIC interoperability standard through the oicmgr framework. Mynewt defines and exposes oicmgr as an OIC Server resource with the following identity and properties: **URI** /omgr **Resource Type**(rt) x.mynewt.nmgr **Interface**(if) oic.if_rw (default), oic.if.baseline **Discoverable** Yes The newtmgr application tool uses CoAP (Constrained Application Protocol) requests to send commands to oicmgr. It sends a CoAP request for /omgr as follows: Specifies the newtmgr command to execute in the URI query string. Uses a GET method for newtmgr commands that retreive information from your application, for example, the taskstats and mpstats commands. Uses a PUT method for newtmgr commands that send data to or modify the state of your application, for example, the echo or datetime commands. Sends the CBOR-encoded command request data in the CoAP message payload. The oicmgr framework supports transport over BLE, serial, and IP connections to the device.","title":"Using Newt Manager in OIC framework"},{"location":"os/modules/devmgmt/oicmgr/#using-the-oic-framework","text":"Apache Mynewt includes support for the OIC interoperability standard through the oicmgr framework. Mynewt defines and exposes oicmgr as an OIC Server resource with the following identity and properties: **URI** /omgr **Resource Type**(rt) x.mynewt.nmgr **Interface**(if) oic.if_rw (default), oic.if.baseline **Discoverable** Yes The newtmgr application tool uses CoAP (Constrained Application Protocol) requests to send commands to oicmgr. It sends a CoAP request for /omgr as follows: Specifies the newtmgr command to execute in the URI query string. Uses a GET method for newtmgr commands that retreive information from your application, for example, the taskstats and mpstats commands. Uses a PUT method for newtmgr commands that send data to or modify the state of your application, for example, the echo or datetime commands. Sends the CBOR-encoded command request data in the CoAP message payload. The oicmgr framework supports transport over BLE, serial, and IP connections to the device.","title":"Using the OIC Framework"},{"location":"os/modules/drivers/driver/","text":"Drivers Description Device drivers in the Mynewt context includes libraries that interface with devices external to the CPU. These devices are connected to the CPU via standard peripherals such as SPI, GPIO, I2C etc. Device drivers leverage the base HAL services in Mynewt to provide friendly abstractions to application developers. +\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014+ | app | +\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014+ | (n)drivers | +\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014+ | HAL | BSP | +\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014+\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014+ The Board Support Package (BSP) abstracts board specific configurations e.g. CPU frequency, input voltage, LED pins, on-chip flash map etc. The Hardware Abstraction Layer (HAL) abstracts architecture-specific functionality. It initializes and enables components within a master processor. It is designed to be portable across all the various MCUs supported in Mynewt (e.g. Nordic's nRF51, Nordic's nRF52, NXP's MK64F12 etc.). It includes code that initializes and manages access to components of the board such as board buses (I2C, PCI, PCMCIA, etc.), off-chip memory (controllers, level 2+ cache, Flash, etc.), and off-chip I/O (Ethernet, RS-232, display, mouse, etc.) The driver sits atop the BSP and HAL. It abstracts the common modes of operation for each peripheral device connected via the standard interfaces to the processor. There may be multiple driver implementations of differing complexities for a particular peripheral device. For example, for an Analog to Digital Converter (ADC) peripheral you might have a simple driver that does blocking ADC reads and uses the HAL only. You might have a more complex driver that can deal with both internal and external ADCs, and has chip specific support for doing things like DMA\u2019ing ADC reads into a buffer and posting an event to a task every \u2019n\u2019 samples. The drivers are the ones that register with the kernel\u2019s power management APIs, and manage turning on and off peripherals and external chipsets, etc. The Mynewt core repository comes with a base set of drivers to help the user get started. General design principles Device drivers should have a consistent structure and unified interface whenever possible. For example, we have a top-level package, \u201cadc\u201d, which contains the interface for all ADC drivers, and then we have the individual implementation of the driver itself. The following source files point to this: high-level ADC API: hw/drivers/adc/include/adc/adc.h implementation of ADC for STM32F4: hw/drivers/adc/adc_stm32f4/src/adc_stm32f4.c (As of the 1.0.0-beta release, ADC for nRF51 and nRF52 are available at an external repo . They are expected to be pulled into the core repo on Apache Mynewt after the license terms are clarified.). The only exported call in this example is int stm32f4_adc_dev_init(struct os_dev *, void *) which is passed as a function pointer to os_dev_create() in hal_bsp.c , when the adc device is created. Device drivers should be easy to use. In Mynewt, creating a device initializes it as well, making it readily available for the user to open, use (e.g. read, configure etc.) and close. Creating a device is simple using os_dev_create(struct os_dev *dev, char *name, uint8_t stage, uint8_t priority, os_dev_init_func_t od_init, void *arg) . The od_init function is defined within the appropriate driver directory e.g. stm32f4_adc_dev_init in hw/drivers/adc/adc_stm32f4/src/adc_stm32f4.c for the ADC device initialization function. The implementation should allow for builds optimized for minimal memory usage. Additional functionality can be enabled by writing a more complex driver (usually based on the simple implementation included by default in the core repository) and optionally compiling the relevant packages in. Typically, only a basic driver that addresses a device\u2019s core functionality (covering ~90% of use cases) is included in the Mynewt core repository, thus keeping the footprint small. The implementation should allow a user to be able to instantiate multiple devices of a certain kind. In the Mynewt environment the user can, for example, maintain separate contexts for multiple ADCs over different peripheral connections such as SPI, I2C etc. It is also possible for a user to use a single peripheral interface (e.g. SPI) to drive multiple devices (e.g. ADC), and in that case the device driver has to handle the proper synchronization of the various tasks. Device drivers should be MCU independent. In Mynewt, device creation and operation functions are independent of the underlying MCU. Device drivers should be able to offer high-level interfaces for generic operations common to a particular device group. An example of such a class or group of devices is a group for sensors with generic operations such as channel discovery, configure, and read values. The organization of the driver directory is work in progress - so we encourage you to hop on the dev@ mailing list and offer your insights! Device drivers should be searchable. The plan is to have the newt tool offer a newt pkg search capability. This is work in progress. You are welcome to join the conversation on the dev@ mailing list! Example The Mynewt core repo includes an example of a driver using the HAL to provide extra functionality - the UART driver. It uses HAL GPIO and UART to provide multiple serial ports on the NRF52 (but allowed on other platforms too.) The gist of the driver design is that there is an API for the driver (for use by applications), and then sub-packages to that driver that implement that driver API using the HAL and BSP APIs. Implemented drivers Drivers live under hw/drivers . The current list of supported drivers includes: Driver Description adc TODO: ADC driver. flash SPI/I2C flash drivers. lwip TODO: LWIP. mmc MMC/SD card driver. nimble NIMBLE. sensors TODO: sensors. uart TODO: UART driver.","title":"toc"},{"location":"os/modules/drivers/driver/#drivers","text":"","title":"Drivers"},{"location":"os/modules/drivers/driver/#description","text":"Device drivers in the Mynewt context includes libraries that interface with devices external to the CPU. These devices are connected to the CPU via standard peripherals such as SPI, GPIO, I2C etc. Device drivers leverage the base HAL services in Mynewt to provide friendly abstractions to application developers. +\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014+ | app | +\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014+ | (n)drivers | +\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014+ | HAL | BSP | +\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014+\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014+ The Board Support Package (BSP) abstracts board specific configurations e.g. CPU frequency, input voltage, LED pins, on-chip flash map etc. The Hardware Abstraction Layer (HAL) abstracts architecture-specific functionality. It initializes and enables components within a master processor. It is designed to be portable across all the various MCUs supported in Mynewt (e.g. Nordic's nRF51, Nordic's nRF52, NXP's MK64F12 etc.). It includes code that initializes and manages access to components of the board such as board buses (I2C, PCI, PCMCIA, etc.), off-chip memory (controllers, level 2+ cache, Flash, etc.), and off-chip I/O (Ethernet, RS-232, display, mouse, etc.) The driver sits atop the BSP and HAL. It abstracts the common modes of operation for each peripheral device connected via the standard interfaces to the processor. There may be multiple driver implementations of differing complexities for a particular peripheral device. For example, for an Analog to Digital Converter (ADC) peripheral you might have a simple driver that does blocking ADC reads and uses the HAL only. You might have a more complex driver that can deal with both internal and external ADCs, and has chip specific support for doing things like DMA\u2019ing ADC reads into a buffer and posting an event to a task every \u2019n\u2019 samples. The drivers are the ones that register with the kernel\u2019s power management APIs, and manage turning on and off peripherals and external chipsets, etc. The Mynewt core repository comes with a base set of drivers to help the user get started.","title":"Description"},{"location":"os/modules/drivers/driver/#general-design-principles","text":"Device drivers should have a consistent structure and unified interface whenever possible. For example, we have a top-level package, \u201cadc\u201d, which contains the interface for all ADC drivers, and then we have the individual implementation of the driver itself. The following source files point to this: high-level ADC API: hw/drivers/adc/include/adc/adc.h implementation of ADC for STM32F4: hw/drivers/adc/adc_stm32f4/src/adc_stm32f4.c (As of the 1.0.0-beta release, ADC for nRF51 and nRF52 are available at an external repo . They are expected to be pulled into the core repo on Apache Mynewt after the license terms are clarified.). The only exported call in this example is int stm32f4_adc_dev_init(struct os_dev *, void *) which is passed as a function pointer to os_dev_create() in hal_bsp.c , when the adc device is created. Device drivers should be easy to use. In Mynewt, creating a device initializes it as well, making it readily available for the user to open, use (e.g. read, configure etc.) and close. Creating a device is simple using os_dev_create(struct os_dev *dev, char *name, uint8_t stage, uint8_t priority, os_dev_init_func_t od_init, void *arg) . The od_init function is defined within the appropriate driver directory e.g. stm32f4_adc_dev_init in hw/drivers/adc/adc_stm32f4/src/adc_stm32f4.c for the ADC device initialization function. The implementation should allow for builds optimized for minimal memory usage. Additional functionality can be enabled by writing a more complex driver (usually based on the simple implementation included by default in the core repository) and optionally compiling the relevant packages in. Typically, only a basic driver that addresses a device\u2019s core functionality (covering ~90% of use cases) is included in the Mynewt core repository, thus keeping the footprint small. The implementation should allow a user to be able to instantiate multiple devices of a certain kind. In the Mynewt environment the user can, for example, maintain separate contexts for multiple ADCs over different peripheral connections such as SPI, I2C etc. It is also possible for a user to use a single peripheral interface (e.g. SPI) to drive multiple devices (e.g. ADC), and in that case the device driver has to handle the proper synchronization of the various tasks. Device drivers should be MCU independent. In Mynewt, device creation and operation functions are independent of the underlying MCU. Device drivers should be able to offer high-level interfaces for generic operations common to a particular device group. An example of such a class or group of devices is a group for sensors with generic operations such as channel discovery, configure, and read values. The organization of the driver directory is work in progress - so we encourage you to hop on the dev@ mailing list and offer your insights! Device drivers should be searchable. The plan is to have the newt tool offer a newt pkg search capability. This is work in progress. You are welcome to join the conversation on the dev@ mailing list!","title":"General design principles"},{"location":"os/modules/drivers/driver/#example","text":"The Mynewt core repo includes an example of a driver using the HAL to provide extra functionality - the UART driver. It uses HAL GPIO and UART to provide multiple serial ports on the NRF52 (but allowed on other platforms too.) The gist of the driver design is that there is an API for the driver (for use by applications), and then sub-packages to that driver that implement that driver API using the HAL and BSP APIs.","title":"Example"},{"location":"os/modules/drivers/driver/#implemented-drivers","text":"Drivers live under hw/drivers . The current list of supported drivers includes: Driver Description adc TODO: ADC driver. flash SPI/I2C flash drivers. lwip TODO: LWIP. mmc MMC/SD card driver. nimble NIMBLE. sensors TODO: sensors. uart TODO: UART driver.","title":"Implemented drivers"},{"location":"os/modules/drivers/flash/","text":"flash The flash driver subsystem is a work in progress which aims at supporting common external SPI/I2C flash/eeprom memory chips. This is equivalent to what Linux calls MTD for Memory Technology Devices . At the moment the only flash device that is already supported is the AT45DBxxx SPI flash family with the at45db driver. The flash driver aims for full compatibility with the hal_flash API, which means initialization and usage can be performed by any fs that supports the hal_flash interface. Initialization To be compatible with the standard hal_flash interface, the at45db driver embeds a struct hal_flash to its own struct at45db_dev . The whole at45db_dev struct is shown below. struct at45db_dev { struct hal_flash hal ; struct hal_spi_settings *settings ; int spi_num ; void *spi_cfg ; /** Low-level MCU SPI config */ int ss_pin ; uint32_t baudrate ; uint16_t page_size ; /** Page size to be used, valid: 512 and 528 */ uint8_t disable_auto_erase ; /** Reads and writes auto-erase by default */ }; To ease with initialization a helper function at45db_default_config was added. It returns an already initialized struct at45db_dev leaving the user with just having to provide the SPI related config. To initialize the device, pass the at45db_dev struct to at45db_init . int at45db_init ( const struct hal_flash *dev ); For low-level access to the device the following functions are provided: int at45db_read ( const struct hal_flash *dev , uint32_t addr , void *buf , uint32_t len ); int at45db_write ( const struct hal_flash *dev , uint32_t addr , const void *buf , uint32_t len ); int at45db_erase_sector ( const struct hal_flash *dev , uint32_t sector_address ); int at45db_sector_info ( const struct hal_flash *dev , int idx , uint32_t *address , uint32_t *sz ); Also, nffs is able to run on the device due to the fact that standard hal_flash interface compatibility is provided. Due to current limitations of nffs , it can only run on at45db if the internal flash of the MCU is not being used. Dependencies To include the at45db driver on a project, just include it as a dependency in your pkg.yml: pkg.deps: - hw/drivers/flash/at45db Header file The at45db SPI flash follows the standard hal_flash interface but requires that a special struct #include <at45db/at45db.h> Example This following examples assume that the at45db is being used on a STM32F4 MCU. static const int SPI_SS_PIN = MCU_GPIO_PORTA ( 4 ); static const int SPI_SCK_PIN = MCU_GPIO_PORTA ( 5 ); static const int SPI_MISO_PIN = MCU_GPIO_PORTA ( 6 ); static const int SPI_MOSI_PIN = MCU_GPIO_PORTA ( 7 ); struct stm32f4_hal_spi_cfg spi_cfg = { . ss_pin = SPI_SS_PIN , . sck_pin = SPI_SCK_PIN , . miso_pin = SPI_MISO_PIN , . mosi_pin = SPI_MOSI_PIN , . irq_prio = 2 }; struct at45db_dev *my_at45db_dev = NULL ; my_at45db_dev = at45db_default_config (); my_at45db_dev->spi_num = 0 ; my_at45db_dev->spi_cfg = &spi_cfg ; my_at45db_dev->ss_pin = spi_cfg . ss_pin ; rc = at45db_init (( struct hal_flash * ) my_at45db_dev ); if ( rc ) { /* XXX: error handling */ } The enable nffs to run on the at45db , the flash_id 0 needs to map to provide a mapping from 0 to this struct. const struct hal_flash * hal_bsp_flash_dev ( uint8_t id ) { if ( id != 0 ) { return NULL ; } return &my_at45db_dev ; }","title":"flash"},{"location":"os/modules/drivers/flash/#flash","text":"The flash driver subsystem is a work in progress which aims at supporting common external SPI/I2C flash/eeprom memory chips. This is equivalent to what Linux calls MTD for Memory Technology Devices . At the moment the only flash device that is already supported is the AT45DBxxx SPI flash family with the at45db driver. The flash driver aims for full compatibility with the hal_flash API, which means initialization and usage can be performed by any fs that supports the hal_flash interface.","title":"flash"},{"location":"os/modules/drivers/flash/#initialization","text":"To be compatible with the standard hal_flash interface, the at45db driver embeds a struct hal_flash to its own struct at45db_dev . The whole at45db_dev struct is shown below. struct at45db_dev { struct hal_flash hal ; struct hal_spi_settings *settings ; int spi_num ; void *spi_cfg ; /** Low-level MCU SPI config */ int ss_pin ; uint32_t baudrate ; uint16_t page_size ; /** Page size to be used, valid: 512 and 528 */ uint8_t disable_auto_erase ; /** Reads and writes auto-erase by default */ }; To ease with initialization a helper function at45db_default_config was added. It returns an already initialized struct at45db_dev leaving the user with just having to provide the SPI related config. To initialize the device, pass the at45db_dev struct to at45db_init . int at45db_init ( const struct hal_flash *dev ); For low-level access to the device the following functions are provided: int at45db_read ( const struct hal_flash *dev , uint32_t addr , void *buf , uint32_t len ); int at45db_write ( const struct hal_flash *dev , uint32_t addr , const void *buf , uint32_t len ); int at45db_erase_sector ( const struct hal_flash *dev , uint32_t sector_address ); int at45db_sector_info ( const struct hal_flash *dev , int idx , uint32_t *address , uint32_t *sz ); Also, nffs is able to run on the device due to the fact that standard hal_flash interface compatibility is provided. Due to current limitations of nffs , it can only run on at45db if the internal flash of the MCU is not being used.","title":"Initialization"},{"location":"os/modules/drivers/flash/#dependencies","text":"To include the at45db driver on a project, just include it as a dependency in your pkg.yml: pkg.deps: - hw/drivers/flash/at45db","title":"Dependencies"},{"location":"os/modules/drivers/flash/#header-file","text":"The at45db SPI flash follows the standard hal_flash interface but requires that a special struct #include <at45db/at45db.h>","title":"Header file"},{"location":"os/modules/drivers/flash/#example","text":"This following examples assume that the at45db is being used on a STM32F4 MCU. static const int SPI_SS_PIN = MCU_GPIO_PORTA ( 4 ); static const int SPI_SCK_PIN = MCU_GPIO_PORTA ( 5 ); static const int SPI_MISO_PIN = MCU_GPIO_PORTA ( 6 ); static const int SPI_MOSI_PIN = MCU_GPIO_PORTA ( 7 ); struct stm32f4_hal_spi_cfg spi_cfg = { . ss_pin = SPI_SS_PIN , . sck_pin = SPI_SCK_PIN , . miso_pin = SPI_MISO_PIN , . mosi_pin = SPI_MOSI_PIN , . irq_prio = 2 }; struct at45db_dev *my_at45db_dev = NULL ; my_at45db_dev = at45db_default_config (); my_at45db_dev->spi_num = 0 ; my_at45db_dev->spi_cfg = &spi_cfg ; my_at45db_dev->ss_pin = spi_cfg . ss_pin ; rc = at45db_init (( struct hal_flash * ) my_at45db_dev ); if ( rc ) { /* XXX: error handling */ } The enable nffs to run on the at45db , the flash_id 0 needs to map to provide a mapping from 0 to this struct. const struct hal_flash * hal_bsp_flash_dev ( uint8_t id ) { if ( id != 0 ) { return NULL ; } return &my_at45db_dev ; }","title":"Example"},{"location":"os/modules/drivers/mmc/","text":"mmc The MMC driver provides support for SPI based MMC/SDcard interfaces. It exports a disk_ops struct that can be used by any FS. Currently only fatfs can run over MMC. Initialization int mmc_init ( int spi_num , void *spi_cfg , int ss_pin ) Initializes the mmc driver to be used by a FS. MMC uses the hal_gpio interface to access the SPI ss_pin and the hal_spi interface for the communication with the card. spi_cfg must be a hw dependent structure used by hal_spi_init to initialize the SPI subsystem. Dependencies To include the mmc driver on a project, just include it as a dependency in your pkg.yml: pkg.deps: - hw/drivers/mmc Returned values MMC functions return one of the following status codes: Return code Description MMC_OK Success. MMC_CARD_ERROR General failure on the card. MMC_READ_ERROR Error reading from the card. MMC_WRITE_ERROR Error writing to the card. MMC_TIMEOUT Timed out waiting for the execution of a command. MMC_PARAM_ERROR An invalid parameter was given to a function. MMC_CRC_ERROR CRC error reading card. MMC_DEVICE_ERROR Tried to use an invalid device. MMC_RESPONSE_ERROR A command received an invalid response. MMC_VOLTAGE_ERROR The interface doesn't support the requested voltage. MMC_INVALID_COMMAND The interface haven't accepted some command. MMC_ERASE_ERROR Error erasing the current card. MMC_ADDR_ERROR Tried to access an invalid address. Header file #include \"mmc/mmc.h\" Example This example runs on the STM32F4-Discovery and prints out a listing of the root directory on the currently installed card. // NOTE: error handling removed for clarity! struct stm32f4_hal_spi_cfg spi_cfg = { . ss_pin = SPI_SS_PIN , . sck_pin = SPI_SCK_PIN , . miso_pin = SPI_MISO_PIN , . mosi_pin = SPI_MOSI_PIN , . irq_prio = 2 }; mmc_init ( 0 , &spi_cfg , spi_cfg . ss_pin ); disk_register ( \"mmc0\" , \"fatfs\" , &mmc_ops ); fs_opendir ( \"mmc0:/\" , &dir ); while ( 1 ) { rc = fs_readdir ( dir , &dirent ); if ( rc == FS_ENOENT ) { break ; } fs_dirent_name ( dirent , sizeof ( out_name ), out_name , &u8_len ); printf ( \"%s\\n\" , out_name ); } fs_closedir ( dir );","title":"mmc"},{"location":"os/modules/drivers/mmc/#mmc","text":"The MMC driver provides support for SPI based MMC/SDcard interfaces. It exports a disk_ops struct that can be used by any FS. Currently only fatfs can run over MMC.","title":"mmc"},{"location":"os/modules/drivers/mmc/#initialization","text":"int mmc_init ( int spi_num , void *spi_cfg , int ss_pin ) Initializes the mmc driver to be used by a FS. MMC uses the hal_gpio interface to access the SPI ss_pin and the hal_spi interface for the communication with the card. spi_cfg must be a hw dependent structure used by hal_spi_init to initialize the SPI subsystem.","title":"Initialization"},{"location":"os/modules/drivers/mmc/#dependencies","text":"To include the mmc driver on a project, just include it as a dependency in your pkg.yml: pkg.deps: - hw/drivers/mmc","title":"Dependencies"},{"location":"os/modules/drivers/mmc/#returned-values","text":"MMC functions return one of the following status codes: Return code Description MMC_OK Success. MMC_CARD_ERROR General failure on the card. MMC_READ_ERROR Error reading from the card. MMC_WRITE_ERROR Error writing to the card. MMC_TIMEOUT Timed out waiting for the execution of a command. MMC_PARAM_ERROR An invalid parameter was given to a function. MMC_CRC_ERROR CRC error reading card. MMC_DEVICE_ERROR Tried to use an invalid device. MMC_RESPONSE_ERROR A command received an invalid response. MMC_VOLTAGE_ERROR The interface doesn't support the requested voltage. MMC_INVALID_COMMAND The interface haven't accepted some command. MMC_ERASE_ERROR Error erasing the current card. MMC_ADDR_ERROR Tried to access an invalid address.","title":"Returned values"},{"location":"os/modules/drivers/mmc/#header-file","text":"#include \"mmc/mmc.h\"","title":"Header file"},{"location":"os/modules/drivers/mmc/#example","text":"This example runs on the STM32F4-Discovery and prints out a listing of the root directory on the currently installed card. // NOTE: error handling removed for clarity! struct stm32f4_hal_spi_cfg spi_cfg = { . ss_pin = SPI_SS_PIN , . sck_pin = SPI_SCK_PIN , . miso_pin = SPI_MISO_PIN , . mosi_pin = SPI_MOSI_PIN , . irq_prio = 2 }; mmc_init ( 0 , &spi_cfg , spi_cfg . ss_pin ); disk_register ( \"mmc0\" , \"fatfs\" , &mmc_ops ); fs_opendir ( \"mmc0:/\" , &dir ); while ( 1 ) { rc = fs_readdir ( dir , &dirent ); if ( rc == FS_ENOENT ) { break ; } fs_dirent_name ( dirent , sizeof ( out_name ), out_name , &u8_len ); printf ( \"%s\\n\" , out_name ); } fs_closedir ( dir );","title":"Example"},{"location":"os/modules/elua/elua/","text":"elua Description This package contains a Lua interpreter. See http://lua.org for documentation of the language. You can execute lua scripts either from console with shell or start the execution programmatically. Data structures Notes Currently we don't have language extension modules which would go together with this one, but those should be added. List of Functions Function Description lua_init Registers 'lua' command with shell. lua_main Executes lua script in current task's context. Arguments given are passed to lua interpreter.","title":"elua"},{"location":"os/modules/elua/elua/#elua","text":"","title":"elua"},{"location":"os/modules/elua/elua/#description","text":"This package contains a Lua interpreter. See http://lua.org for documentation of the language. You can execute lua scripts either from console with shell or start the execution programmatically.","title":"Description"},{"location":"os/modules/elua/elua/#data-structures","text":"","title":"Data structures"},{"location":"os/modules/elua/elua/#notes","text":"Currently we don't have language extension modules which would go together with this one, but those should be added.","title":"Notes"},{"location":"os/modules/elua/elua/#list-of-functions","text":"Function Description lua_init Registers 'lua' command with shell. lua_main Executes lua script in current task's context. Arguments given are passed to lua interpreter.","title":"List of Functions"},{"location":"os/modules/elua/lua_init/","text":"lua_init int lua_init(void) Registers 'lua' command with shell. This function should be called while initializing the project, preferably after shell itself has been initialized. Arguments N/A Returned values Returns Notes Calling this is meaningful only if you include the shell package in your project. Example int main(int argc, char **argv) { ... shell_task_init(SHELL_TASK_PRIO, shell_stack, SHELL_TASK_STACK_SIZE, SHELL_MAX_INPUT_LEN); ... lua_init(); ... }","title":"Lua init"},{"location":"os/modules/elua/lua_init/#lua_init","text":"int lua_init(void) Registers 'lua' command with shell. This function should be called while initializing the project, preferably after shell itself has been initialized.","title":" lua_init "},{"location":"os/modules/elua/lua_init/#arguments","text":"N/A","title":"Arguments"},{"location":"os/modules/elua/lua_init/#returned-values","text":"Returns","title":"Returned values"},{"location":"os/modules/elua/lua_init/#notes","text":"Calling this is meaningful only if you include the shell package in your project.","title":"Notes"},{"location":"os/modules/elua/lua_init/#example","text":"int main(int argc, char **argv) { ... shell_task_init(SHELL_TASK_PRIO, shell_stack, SHELL_TASK_STACK_SIZE, SHELL_MAX_INPUT_LEN); ... lua_init(); ... }","title":"Example"},{"location":"os/modules/elua/lua_main/","text":"lua_main int lua_main(int argc, char **argv) Executes lua script in current task's context. Arguments given are passed to lua interpreter. Arguments Arguments Description argc Number of elements in argv array argv Array of character strings Returned values Returns the return code from the lua interpreter. Notes Example static int lua_cmd(int argc, char **argv) { lua_main(argc, argv); return 0; }","title":"Lua main"},{"location":"os/modules/elua/lua_main/#lua_main","text":"int lua_main(int argc, char **argv) Executes lua script in current task's context. Arguments given are passed to lua interpreter.","title":" lua_main "},{"location":"os/modules/elua/lua_main/#arguments","text":"Arguments Description argc Number of elements in argv array argv Array of character strings","title":"Arguments"},{"location":"os/modules/elua/lua_main/#returned-values","text":"Returns the return code from the lua interpreter.","title":"Returned values"},{"location":"os/modules/elua/lua_main/#notes","text":"","title":"Notes"},{"location":"os/modules/elua/lua_main/#example","text":"static int lua_cmd(int argc, char **argv) { lua_main(argc, argv); return 0; }","title":"Example"},{"location":"os/modules/fcb/fcb/","text":"Flash Circular Buffer (FCB) Flash circular buffer provides an abstration through which you can treat flash like a FIFO. You append entries to the end, and read data from the beginning. Description Elements in the flash contain the length of the element, the data within the element, and checksum over the element contents. Storage of elements in flash is done in a FIFO fashion. When user requests space for the next element, space is located at the end of the used area. When user starts reading, the first element served is the oldest element in flash. Elements can be appended to the end of the area until storage space is exhausted. User has control over what happens next; either erase oldest block of data, thereby freeing up some space, or stop writing new data until existing data has been collected. FCB treats underlying storage as an array of flash sectors; when it erases old data, it does this a sector at a time. Elements in the flash are checksummed. That is how FCB detects whether writing element to flash completed ok. It will skip over entries which don't have a valid checksum. Usage To add an element to circular buffer: Call fcb_append() to get the location where data can be written. If this fails due to lack of space, you can call fcb_rotate() to make some. And then call fcb_append() again. Use flash_area_write() to write element contents. Call fcb_append_finish() when done. This completes the entry by calculating the checksum. To read contents of the circular buffer: * Call fcb_walk() with a pointer to your callback function. * Within callback function copy in data from the element using flash_area_read(). You can tell when all data from within a sector has been read by monitoring returned element's area pointer. Then you can call fcb_rotate(), if you're done with that data. Alternatively: * Call fcb_getnext() with 0 in element offset to get the pointer to oldest element. * Use flash_area_read() to read element contents. * Call fcb_getnext() with pointer to current element to get the next one. And so on. Data structures This data structure describes the element location in the flash. You would use it figure out what parameters to pass to flash_area_read() to read element contents. Or to flash_area_write() when adding a new element. struct fcb_entry { struct flash_area *fe_area ; uint32_t fe_elem_off ; uint32_t fe_data_off ; uint16_t fe_data_len ; }; Element Description fe_area Pointer to info about the flash sector. Pass this to flash_area_xx() routines. fe_elem_off Byte offset from the start of the sector to beginning of element. fe_data_off Byte offset from start of the sector to beginning of element data. Pass this to to flash_area_xx() routines. fe_data_len Number of bytes in the element. The following data structure describes the FCB itself. First part should be filled in by the user before calling fcb_init(). The second part is used by FCB for its internal bookkeeping. struct fcb { /* Caller of fcb_init fills this in */ uint32_t f_magic ; /* As placed on the disk */ uint8_t f_version ; /* Current version number of the data */ uint8_t f_sector_cnt ; /* Number of elements in sector array */ uint8_t f_scratch_cnt ; /* How many sectors should be kept empty */ struct flash_area *f_sectors ; /* Array of sectors, must be contiguous */ /* Flash circular buffer internal state */ struct os_mutex f_mtx ; /* Locking for accessing the FCB data */ struct flash_area *f_oldest ; struct fcb_entry f_active ; uint16_t f_active_id ; uint8_t f_align ; /* writes to flash have to aligned to this */ }; Element Description f_magic Magic number in the beginning of FCB flash sector. FCB uses this when determining whether sector contains valid data or not. f_version Current version number of the data. Also stored in flash sector header. f_sector_cnt Number of elements in the f_sectors array. f_scratch_cnt Number of sectors to keep empty. This can be used if you need to have scratch space for garbage collecting when FCB fills up. f_sectors Array of entries describing flash sectors to use. f_mtx Lock protecting access to FCBs internal data. f_oldest Pointer to flash sector containing the oldest data. This is where data is served when read is started. f_active Flash location where the newest data is. This is used by fcb_append() to figure out where the data should go to. f_active_id Flash sectors are assigned ever-increasing serial numbers. This is how FCB figures out where oldest data is on system restart. f_align Some flashes have restrictions on alignment for writes. FCB keeps a copy of this number for the flash here. List of Functions The functions available in this OS feature are: Function Description fcb_init Initializes the FCB. After calling this, you can start reading/writing data from FCB. fcb_append Start writing a new element to flash. fcb_append_finish Finalizes the write of new element. FCB computes the checksum over the element and updates it in flash. fcb_walk Walks over all log entries in FCB. fcb_getnext Fills given FCB location with information about next element. fcb_rotate Erase the oldest sector in FCB. fcb_append_to_scratch If FCB uses scratch blocks, use reserve blocks when FCB is filled. fcb_is_empty Returns 1 if there are no elements stored in FCB, otherwise returns 0. fcb_offset_last_n Returns the offset of n-th last element. fcb_clear Wipes out all data in FCB.","title":"toc"},{"location":"os/modules/fcb/fcb/#flash-circular-buffer-fcb","text":"Flash circular buffer provides an abstration through which you can treat flash like a FIFO. You append entries to the end, and read data from the beginning.","title":"Flash Circular Buffer (FCB)"},{"location":"os/modules/fcb/fcb/#description","text":"Elements in the flash contain the length of the element, the data within the element, and checksum over the element contents. Storage of elements in flash is done in a FIFO fashion. When user requests space for the next element, space is located at the end of the used area. When user starts reading, the first element served is the oldest element in flash. Elements can be appended to the end of the area until storage space is exhausted. User has control over what happens next; either erase oldest block of data, thereby freeing up some space, or stop writing new data until existing data has been collected. FCB treats underlying storage as an array of flash sectors; when it erases old data, it does this a sector at a time. Elements in the flash are checksummed. That is how FCB detects whether writing element to flash completed ok. It will skip over entries which don't have a valid checksum.","title":"Description"},{"location":"os/modules/fcb/fcb/#usage","text":"To add an element to circular buffer: Call fcb_append() to get the location where data can be written. If this fails due to lack of space, you can call fcb_rotate() to make some. And then call fcb_append() again. Use flash_area_write() to write element contents. Call fcb_append_finish() when done. This completes the entry by calculating the checksum. To read contents of the circular buffer: * Call fcb_walk() with a pointer to your callback function. * Within callback function copy in data from the element using flash_area_read(). You can tell when all data from within a sector has been read by monitoring returned element's area pointer. Then you can call fcb_rotate(), if you're done with that data. Alternatively: * Call fcb_getnext() with 0 in element offset to get the pointer to oldest element. * Use flash_area_read() to read element contents. * Call fcb_getnext() with pointer to current element to get the next one. And so on.","title":"Usage"},{"location":"os/modules/fcb/fcb/#data-structures","text":"This data structure describes the element location in the flash. You would use it figure out what parameters to pass to flash_area_read() to read element contents. Or to flash_area_write() when adding a new element. struct fcb_entry { struct flash_area *fe_area ; uint32_t fe_elem_off ; uint32_t fe_data_off ; uint16_t fe_data_len ; }; Element Description fe_area Pointer to info about the flash sector. Pass this to flash_area_xx() routines. fe_elem_off Byte offset from the start of the sector to beginning of element. fe_data_off Byte offset from start of the sector to beginning of element data. Pass this to to flash_area_xx() routines. fe_data_len Number of bytes in the element. The following data structure describes the FCB itself. First part should be filled in by the user before calling fcb_init(). The second part is used by FCB for its internal bookkeeping. struct fcb { /* Caller of fcb_init fills this in */ uint32_t f_magic ; /* As placed on the disk */ uint8_t f_version ; /* Current version number of the data */ uint8_t f_sector_cnt ; /* Number of elements in sector array */ uint8_t f_scratch_cnt ; /* How many sectors should be kept empty */ struct flash_area *f_sectors ; /* Array of sectors, must be contiguous */ /* Flash circular buffer internal state */ struct os_mutex f_mtx ; /* Locking for accessing the FCB data */ struct flash_area *f_oldest ; struct fcb_entry f_active ; uint16_t f_active_id ; uint8_t f_align ; /* writes to flash have to aligned to this */ }; Element Description f_magic Magic number in the beginning of FCB flash sector. FCB uses this when determining whether sector contains valid data or not. f_version Current version number of the data. Also stored in flash sector header. f_sector_cnt Number of elements in the f_sectors array. f_scratch_cnt Number of sectors to keep empty. This can be used if you need to have scratch space for garbage collecting when FCB fills up. f_sectors Array of entries describing flash sectors to use. f_mtx Lock protecting access to FCBs internal data. f_oldest Pointer to flash sector containing the oldest data. This is where data is served when read is started. f_active Flash location where the newest data is. This is used by fcb_append() to figure out where the data should go to. f_active_id Flash sectors are assigned ever-increasing serial numbers. This is how FCB figures out where oldest data is on system restart. f_align Some flashes have restrictions on alignment for writes. FCB keeps a copy of this number for the flash here.","title":"Data structures"},{"location":"os/modules/fcb/fcb/#list-of-functions","text":"The functions available in this OS feature are: Function Description fcb_init Initializes the FCB. After calling this, you can start reading/writing data from FCB. fcb_append Start writing a new element to flash. fcb_append_finish Finalizes the write of new element. FCB computes the checksum over the element and updates it in flash. fcb_walk Walks over all log entries in FCB. fcb_getnext Fills given FCB location with information about next element. fcb_rotate Erase the oldest sector in FCB. fcb_append_to_scratch If FCB uses scratch blocks, use reserve blocks when FCB is filled. fcb_is_empty Returns 1 if there are no elements stored in FCB, otherwise returns 0. fcb_offset_last_n Returns the offset of n-th last element. fcb_clear Wipes out all data in FCB.","title":"List of Functions"},{"location":"os/modules/fcb/fcb_append/","text":"fcb_append int fcb_append(struct fcb *fcb, uint16_t len, struct fcb_entry *append_loc); Start writing a new element to flash. This routine reserves the space in the flash by writing out the element header. When writing the contents for the entry, use append_loc->fl_area and append_loc->fl_data_off as arguments to flash_area_write(). When finished, call fcb_append_finish() with append_loc as argument. Arguments Arguments Description fcb Points to FCB where data is written to. len Number of bytes to reserve for the element. loc Pointer to fcb_entry. fcb_append() will fill this with info about where the element can be written to. Returned values Returns 0 on success; nonzero on failure. FCB_ERR_NOSPACE is returned if FCB is full. Notes If FCB is full, you need to make more space. This can be done by calling fcb_rotate(). Or if you've reserved scratch sectors, you can take those into use by calling fcb_append_to_scratch(). Example","title":"fcb_append"},{"location":"os/modules/fcb/fcb_append/#fcb_append","text":"int fcb_append(struct fcb *fcb, uint16_t len, struct fcb_entry *append_loc); Start writing a new element to flash. This routine reserves the space in the flash by writing out the element header. When writing the contents for the entry, use append_loc->fl_area and append_loc->fl_data_off as arguments to flash_area_write(). When finished, call fcb_append_finish() with append_loc as argument.","title":"fcb_append"},{"location":"os/modules/fcb/fcb_append/#arguments","text":"Arguments Description fcb Points to FCB where data is written to. len Number of bytes to reserve for the element. loc Pointer to fcb_entry. fcb_append() will fill this with info about where the element can be written to.","title":"Arguments"},{"location":"os/modules/fcb/fcb_append/#returned-values","text":"Returns 0 on success; nonzero on failure. FCB_ERR_NOSPACE is returned if FCB is full.","title":"Returned values"},{"location":"os/modules/fcb/fcb_append/#notes","text":"If FCB is full, you need to make more space. This can be done by calling fcb_rotate(). Or if you've reserved scratch sectors, you can take those into use by calling fcb_append_to_scratch().","title":"Notes"},{"location":"os/modules/fcb/fcb_append/#example","text":"","title":"Example"},{"location":"os/modules/fcb/fcb_append_finish/","text":"fcb_append_finish int fcb_append_finish(struct fcb *fcb, struct fcb_entry *append_loc); Finalizes the write of new element. FCB computes the checksum over the element and updates it in flash. Arguments Arguments Description fcb Points to FCB where data is written to. append_loc Pointer to fcb_entry. Use the fcb_entry returned by fcb_append(). Returned values Returns 0 on success; nonzero on failure. Notes You need to call fcb_append_finish() after writing the element contents. Otherwise FCB will consider this entry to be invalid, and skips over it when reading. Example","title":"fcb_append_finish"},{"location":"os/modules/fcb/fcb_append_finish/#fcb_append_finish","text":"int fcb_append_finish(struct fcb *fcb, struct fcb_entry *append_loc); Finalizes the write of new element. FCB computes the checksum over the element and updates it in flash.","title":"fcb_append_finish"},{"location":"os/modules/fcb/fcb_append_finish/#arguments","text":"Arguments Description fcb Points to FCB where data is written to. append_loc Pointer to fcb_entry. Use the fcb_entry returned by fcb_append().","title":"Arguments"},{"location":"os/modules/fcb/fcb_append_finish/#returned-values","text":"Returns 0 on success; nonzero on failure.","title":"Returned values"},{"location":"os/modules/fcb/fcb_append_finish/#notes","text":"You need to call fcb_append_finish() after writing the element contents. Otherwise FCB will consider this entry to be invalid, and skips over it when reading.","title":"Notes"},{"location":"os/modules/fcb/fcb_append_finish/#example","text":"","title":"Example"},{"location":"os/modules/fcb/fcb_append_to_scratch/","text":"fcb_append_to_scratch int fcb_append_to_scratch(struct fcb *fcb); This can be used if FCB created to have scratch block(s). Once FCB fills up with data, fcb_append() will fail. This routine can be called to start using the reserve block. Arguments Arguments Description fcb Points to FCB. Returned values Returns 0 on success; nonzero on failure. Notes Example","title":"fcb_append_to_scratch"},{"location":"os/modules/fcb/fcb_append_to_scratch/#fcb_append_to_scratch","text":"int fcb_append_to_scratch(struct fcb *fcb); This can be used if FCB created to have scratch block(s). Once FCB fills up with data, fcb_append() will fail. This routine can be called to start using the reserve block.","title":"fcb_append_to_scratch"},{"location":"os/modules/fcb/fcb_append_to_scratch/#arguments","text":"Arguments Description fcb Points to FCB.","title":"Arguments"},{"location":"os/modules/fcb/fcb_append_to_scratch/#returned-values","text":"Returns 0 on success; nonzero on failure.","title":"Returned values"},{"location":"os/modules/fcb/fcb_append_to_scratch/#notes","text":"","title":"Notes"},{"location":"os/modules/fcb/fcb_append_to_scratch/#example","text":"","title":"Example"},{"location":"os/modules/fcb/fcb_clear/","text":"fcb_clear int fcb_clear(struct fcb *fcb); Wipes out all data in FCB. Arguments Arguments Description fcb Points to FCB. Returned values Returns 0 on success; non-zero otherwise. Notes Example","title":"fcb_clear"},{"location":"os/modules/fcb/fcb_clear/#fcb_clear","text":"int fcb_clear(struct fcb *fcb); Wipes out all data in FCB.","title":"fcb_clear"},{"location":"os/modules/fcb/fcb_clear/#arguments","text":"Arguments Description fcb Points to FCB.","title":"Arguments"},{"location":"os/modules/fcb/fcb_clear/#returned-values","text":"Returns 0 on success; non-zero otherwise.","title":"Returned values"},{"location":"os/modules/fcb/fcb_clear/#notes","text":"","title":"Notes"},{"location":"os/modules/fcb/fcb_clear/#example","text":"","title":"Example"},{"location":"os/modules/fcb/fcb_getnext/","text":"fcb_getnext int fcb_getnext(struct fcb *, struct fcb_entry *loc); Given element in location in loc, return with loc filled in with information about next element. If loc->le_elem_off is set to 0, fcb_getnext() will return info about the oldest element in FCB. Entry data can be read within the callback using flash_area_read(), using loc->fe_area, loc->fe_data_off, and loc->fe_data_len as arguments. Arguments Arguments Description fcb Points to FCB where data is written to. loc Info about element. On successful call Returned values Returns 0 on success; nonzero on failure. Returns FCB_ERR_NOVAR when there are no more elements left. Notes Example","title":"fcb_getnext"},{"location":"os/modules/fcb/fcb_getnext/#fcb_getnext","text":"int fcb_getnext(struct fcb *, struct fcb_entry *loc); Given element in location in loc, return with loc filled in with information about next element. If loc->le_elem_off is set to 0, fcb_getnext() will return info about the oldest element in FCB. Entry data can be read within the callback using flash_area_read(), using loc->fe_area, loc->fe_data_off, and loc->fe_data_len as arguments.","title":"fcb_getnext"},{"location":"os/modules/fcb/fcb_getnext/#arguments","text":"Arguments Description fcb Points to FCB where data is written to. loc Info about element. On successful call","title":"Arguments"},{"location":"os/modules/fcb/fcb_getnext/#returned-values","text":"Returns 0 on success; nonzero on failure. Returns FCB_ERR_NOVAR when there are no more elements left.","title":"Returned values"},{"location":"os/modules/fcb/fcb_getnext/#notes","text":"","title":"Notes"},{"location":"os/modules/fcb/fcb_getnext/#example","text":"","title":"Example"},{"location":"os/modules/fcb/fcb_init/","text":"fcb_init int fcb_init(struct fcb *); Initializes FCB. This function walks through the given sectors, finding out how much data already exists in the flash. After calling this, you can start reading/writing data from FCB. Arguments Arguments Description fcb Structure describing the FCB. Returned values Returns 0 on success; nonzero on failure. Notes User should fill in their portion of fcb before calling this function. Example","title":"fcb_init"},{"location":"os/modules/fcb/fcb_init/#fcb_init","text":"int fcb_init(struct fcb *); Initializes FCB. This function walks through the given sectors, finding out how much data already exists in the flash. After calling this, you can start reading/writing data from FCB.","title":"fcb_init"},{"location":"os/modules/fcb/fcb_init/#arguments","text":"Arguments Description fcb Structure describing the FCB.","title":"Arguments"},{"location":"os/modules/fcb/fcb_init/#returned-values","text":"Returns 0 on success; nonzero on failure.","title":"Returned values"},{"location":"os/modules/fcb/fcb_init/#notes","text":"User should fill in their portion of fcb before calling this function.","title":"Notes"},{"location":"os/modules/fcb/fcb_init/#example","text":"","title":"Example"},{"location":"os/modules/fcb/fcb_is_empty/","text":"fcb_is_empty int fcb_is_empty(struct fcb *fcb); Returns 1 if there are no elements stored in FCB, otherwise returns 0. Arguments Arguments Description fcb Points to FCB. Returned values See description. Notes Example","title":"fcb_is_empty"},{"location":"os/modules/fcb/fcb_is_empty/#fcb_is_empty","text":"int fcb_is_empty(struct fcb *fcb); Returns 1 if there are no elements stored in FCB, otherwise returns 0.","title":"fcb_is_empty"},{"location":"os/modules/fcb/fcb_is_empty/#arguments","text":"Arguments Description fcb Points to FCB.","title":"Arguments"},{"location":"os/modules/fcb/fcb_is_empty/#returned-values","text":"See description.","title":"Returned values"},{"location":"os/modules/fcb/fcb_is_empty/#notes","text":"","title":"Notes"},{"location":"os/modules/fcb/fcb_is_empty/#example","text":"","title":"Example"},{"location":"os/modules/fcb/fcb_offset_last_n/","text":"fcb_offset_last_n int fcb_offset_last_n(struct fcb *fcb, uint8_t entries, uint32_t *last_n_off); Returns the offset of n-th last element. Arguments Arguments Description fcb Points to FCB. entries How many entries to leave. last_n_off Returned offset. Returned values 0 on success; non-zero on failure. Notes Returned offset is relative to beginning of the sector where the element is. Therefore, n-th last element must be found within the last sector of FCB. Example","title":"fcb_offset_last_n"},{"location":"os/modules/fcb/fcb_offset_last_n/#fcb_offset_last_n","text":"int fcb_offset_last_n(struct fcb *fcb, uint8_t entries, uint32_t *last_n_off); Returns the offset of n-th last element.","title":"fcb_offset_last_n"},{"location":"os/modules/fcb/fcb_offset_last_n/#arguments","text":"Arguments Description fcb Points to FCB. entries How many entries to leave. last_n_off Returned offset.","title":"Arguments"},{"location":"os/modules/fcb/fcb_offset_last_n/#returned-values","text":"0 on success; non-zero on failure.","title":"Returned values"},{"location":"os/modules/fcb/fcb_offset_last_n/#notes","text":"Returned offset is relative to beginning of the sector where the element is. Therefore, n-th last element must be found within the last sector of FCB.","title":"Notes"},{"location":"os/modules/fcb/fcb_offset_last_n/#example","text":"","title":"Example"},{"location":"os/modules/fcb/fcb_rotate/","text":"fcb_rotate int fcb_rotate(struct fcb *fcb); Erase the oldest sector in FCB. Arguments Arguments Description fcb Points to FCB. Returned values Returns 0 on success; nonzero on failure. Notes Example","title":"fcb_rotate"},{"location":"os/modules/fcb/fcb_rotate/#fcb_rotate","text":"int fcb_rotate(struct fcb *fcb); Erase the oldest sector in FCB.","title":"fcb_rotate"},{"location":"os/modules/fcb/fcb_rotate/#arguments","text":"Arguments Description fcb Points to FCB.","title":"Arguments"},{"location":"os/modules/fcb/fcb_rotate/#returned-values","text":"Returns 0 on success; nonzero on failure.","title":"Returned values"},{"location":"os/modules/fcb/fcb_rotate/#notes","text":"","title":"Notes"},{"location":"os/modules/fcb/fcb_rotate/#example","text":"","title":"Example"},{"location":"os/modules/fcb/fcb_walk/","text":"fcb_walk typedef int (*fcb_walk_cb)(struct fcb_entry *loc, void *arg); int fcb_walk(struct fcb *fcb, struct flash_area *area, fcb_walk_cb cb, void *cb_arg); Walks over all log entries in FCB. Callback function cb gets called for every entry. If cb wants to stop the walk, it should return a non-zero value. If specific flash_area is specified, only entries within that sector are walked over. Entry data can be read within the callback using flash_area_read(), using loc->fe_area, loc->fe_data_off, and loc->fe_data_len as arguments. Arguments Arguments Description fcb Points to FCB where data is written to. area Optional. Pointer to specific entry in fcb's array of sectors. cb Callback function which gets called for every valid entry fcb_walk encounters. cb_arg Optional. Parameter which gets passed to callback function. Returned values Returns 0 on success; nonzero on failure. Notes Example","title":"fcb_walk"},{"location":"os/modules/fcb/fcb_walk/#fcb_walk","text":"typedef int (*fcb_walk_cb)(struct fcb_entry *loc, void *arg); int fcb_walk(struct fcb *fcb, struct flash_area *area, fcb_walk_cb cb, void *cb_arg); Walks over all log entries in FCB. Callback function cb gets called for every entry. If cb wants to stop the walk, it should return a non-zero value. If specific flash_area is specified, only entries within that sector are walked over. Entry data can be read within the callback using flash_area_read(), using loc->fe_area, loc->fe_data_off, and loc->fe_data_len as arguments.","title":"fcb_walk"},{"location":"os/modules/fcb/fcb_walk/#arguments","text":"Arguments Description fcb Points to FCB where data is written to. area Optional. Pointer to specific entry in fcb's array of sectors. cb Callback function which gets called for every valid entry fcb_walk encounters. cb_arg Optional. Parameter which gets passed to callback function.","title":"Arguments"},{"location":"os/modules/fcb/fcb_walk/#returned-values","text":"Returns 0 on success; nonzero on failure.","title":"Returned values"},{"location":"os/modules/fcb/fcb_walk/#notes","text":"","title":"Notes"},{"location":"os/modules/fcb/fcb_walk/#example","text":"","title":"Example"},{"location":"os/modules/fs/fatfs/","text":"The FAT File System Mynewt provides an implementation of the FAT filesystem which is currently supported on MMC/SD cards. Description File Allocation Table (FAT) is a computer file system architecture and a family of industry-standard file systems utilizing it. The FAT file system is a legacy file system which is simple and robust. It offers good performance even in lightweight implementations, but cannot deliver the same performance, reliability and scalability as some modern file systems. Configuration fatfs configuration can be tweaked by editing fs/fatfs/include/fatfs/ffconf.h . The current configuraton was chosen to minimize memory use and some options address limitations existing in the OS: Write support is enabled by default (can be disabled to minimize memory use). Long filename (up to 255) support is disabled. When writing files, time/dates are not persisted due to current lack of a standard hal_rtc interface. No unicode support. Vanilla config uses standard US codepage 437. Formatting of new volumes is disabled. Default number of volumes is configured to 1. API To include fatfs on a project just include it as a dependency in your project: pkg.deps: - fs/fatfs It can now be used through the standard file system abstraction functions as described in FS API . Example An example of using fatfs on a MMC card is provided on the MMC documentation.","title":"FAT File System"},{"location":"os/modules/fs/fatfs/#the-fat-file-system","text":"Mynewt provides an implementation of the FAT filesystem which is currently supported on MMC/SD cards.","title":"The FAT File System"},{"location":"os/modules/fs/fatfs/#description","text":"File Allocation Table (FAT) is a computer file system architecture and a family of industry-standard file systems utilizing it. The FAT file system is a legacy file system which is simple and robust. It offers good performance even in lightweight implementations, but cannot deliver the same performance, reliability and scalability as some modern file systems.","title":"Description"},{"location":"os/modules/fs/fatfs/#configuration","text":"fatfs configuration can be tweaked by editing fs/fatfs/include/fatfs/ffconf.h . The current configuraton was chosen to minimize memory use and some options address limitations existing in the OS: Write support is enabled by default (can be disabled to minimize memory use). Long filename (up to 255) support is disabled. When writing files, time/dates are not persisted due to current lack of a standard hal_rtc interface. No unicode support. Vanilla config uses standard US codepage 437. Formatting of new volumes is disabled. Default number of volumes is configured to 1.","title":"Configuration"},{"location":"os/modules/fs/fatfs/#api","text":"To include fatfs on a project just include it as a dependency in your project: pkg.deps: - fs/fatfs It can now be used through the standard file system abstraction functions as described in FS API .","title":"API"},{"location":"os/modules/fs/fatfs/#example","text":"An example of using fatfs on a MMC card is provided on the MMC documentation.","title":"Example"},{"location":"os/modules/fs/otherfs/","text":"Other File Systems Libraries use Mynewt's file system abstraction layer ( fs/fs ) for all file operations. Because clients use an abstraction layer, the underlying file system can be swapped out without affecting client code. This page documents the procedure for plugging a custom file system into the Mynewt file system abstraction layer. 1. Specify fs/fs as a dependency of your file system package. The file system package must register itself with the fs/fs package, so it must specify fs/fs as a dependency. As an example, part of the Newtron Flash File System (nffs) pkg.yml is reproduced below. Notice the first item in the pkg.deps list. pkg.name: fs/nffs pkg.deps: - fs/fs - hw/hal - libs/os - libs/testutil - sys/log 2. Register your package's API with the fs/fs interface. The fs/fs package calls into the underlying file system via a collection of function pointers. To plug your file system into the fs/fs API, you must assign these function pointers to the corresponding routines in your file system package. For example, nffs registers itself with fs/fs as follows (from fs/nffs/src/nffs.c ): static const struct fs_ops nffs_ops = { . f_open = nffs_open , . f_close = nffs_close , . f_read = nffs_read , . f_write = nffs_write , . f_seek = nffs_seek , . f_getpos = nffs_getpos , . f_filelen = nffs_file_len , . f_unlink = nffs_unlink , . f_rename = nffs_rename , . f_mkdir = nffs_mkdir , . f_opendir = nffs_opendir , . f_readdir = nffs_readdir , . f_closedir = nffs_closedir , . f_dirent_name = nffs_dirent_name , . f_dirent_is_dir = nffs_dirent_is_dir , . f_name = \"nffs\" }; int nffs_init ( void ) { /* [...] */ fs_register ( &nffs_ops ); } Header Files To gain access to fs/fs 's registration interface, include the following header: #include \"fs/fs_if.h\"","title":"Other File Systems"},{"location":"os/modules/fs/otherfs/#other-file-systems","text":"Libraries use Mynewt's file system abstraction layer ( fs/fs ) for all file operations. Because clients use an abstraction layer, the underlying file system can be swapped out without affecting client code. This page documents the procedure for plugging a custom file system into the Mynewt file system abstraction layer.","title":"Other File Systems"},{"location":"os/modules/fs/otherfs/#1-specify-fsfs-as-a-dependency-of-your-file-system-package","text":"The file system package must register itself with the fs/fs package, so it must specify fs/fs as a dependency. As an example, part of the Newtron Flash File System (nffs) pkg.yml is reproduced below. Notice the first item in the pkg.deps list. pkg.name: fs/nffs pkg.deps: - fs/fs - hw/hal - libs/os - libs/testutil - sys/log","title":"1. Specify fs/fs as a dependency of your file system package."},{"location":"os/modules/fs/otherfs/#2-register-your-packages-api-with-the-fsfs-interface","text":"The fs/fs package calls into the underlying file system via a collection of function pointers. To plug your file system into the fs/fs API, you must assign these function pointers to the corresponding routines in your file system package. For example, nffs registers itself with fs/fs as follows (from fs/nffs/src/nffs.c ): static const struct fs_ops nffs_ops = { . f_open = nffs_open , . f_close = nffs_close , . f_read = nffs_read , . f_write = nffs_write , . f_seek = nffs_seek , . f_getpos = nffs_getpos , . f_filelen = nffs_file_len , . f_unlink = nffs_unlink , . f_rename = nffs_rename , . f_mkdir = nffs_mkdir , . f_opendir = nffs_opendir , . f_readdir = nffs_readdir , . f_closedir = nffs_closedir , . f_dirent_name = nffs_dirent_name , . f_dirent_is_dir = nffs_dirent_is_dir , . f_name = \"nffs\" }; int nffs_init ( void ) { /* [...] */ fs_register ( &nffs_ops ); }","title":"2. Register your package's API with the fs/fs interface."},{"location":"os/modules/fs/otherfs/#header-files","text":"To gain access to fs/fs 's registration interface, include the following header: #include \"fs/fs_if.h\"","title":"Header Files"},{"location":"os/modules/fs/fs/fs/","text":"File System Abstraction Mynewt provides a file system abstraction layer ( fs/fs ) to allow client code to be file system agnostic. By accessing the file system via the fs/fs API, client code can perform file system operations without being tied to a particular implementation. When possible, library code should use the fs/fs API rather than accessing the underlying file system directly. Description Applications should aim to minimize the amount of code which depends on a particular file system implementation. When possible, only depend on the fs/fs package. In terms of the Mynewt hierarchy, an app package must depend on a specific file system package, while library packages should only depend on fs/fs . Applications wanting to access a filesystem are required to include the necessary packages in their applications pkg.yml file. In the following example, the Newtron Flash File System is used. # repos/apache-mynewt-core/apps/slinky/pkg.yml pkg.name: repos/apache-mynewt-core/apps/slinky pkg.deps: - fs/fs # include the file operations interfaces - fs/nffs # include the NFFS filesystem implementation # repos/apache-mynewt-core/apps/slinky/syscfg.yml # [...] # Package: apps/<example app> # [...] CONFIG_NFFS: 1 # initialize and configure NFFS into the system # NFFS_DETECT_FAIL: 1 # Ignore NFFS detection issues # NFFS_DETECT_FAIL: 2 # Format a new NFFS file system on failure to detect # [...] Consult the documentation for nffs for a more detailed explanation of NFFS_DETECT_FAIL Code which uses the file system after the system has been initialized need only depend on fs/fs . For example, the libs/imgmgr package is a library which provides firmware upload and download functionality via the use of a file system. This library is only used after the system has been initialized, and therefore only depends on the fs/fs package. # repos/apache-mynewt-core/libs/imgmgr/pkg.yml pkg.name: libs/imgmgr pkg.deps: - fs/fs # [...] The libs/imgmgr package uses the fs/fs API for all file system operations. Support for multiple filesystems When using a single filesystem/disk, it is valid to provide paths in the standard unix way, eg, /<dir-name>/<file-name> . When trying to run more than one filesystem or a single filesystem in multiple devices simultaneosly, an extra name has to be given to the disk that is being used. The abstraction for that was added as the fs/disk package which is a dependency of fs/fs . It adds the following extra user function: int disk_register ( const char *disk_name , const char *fs_name , struct disk_ops *dops ) As an example os usage: disk_register ( \"mmc0\" , \"fatfs\" , &mmc_ops ); disk_register ( \"flash0\" , \"nffs\" , NULL ); This registers the name mmc0 to use fatfs as the filesystem and mmc_ops for the low-level disk driver and also registers flash0 to use nffs . nffs is currently strongly bound to the hal_flash interface, ignoring any other possible disk_ops given. struct disk_ops To support a new low-level disk interface, the struct disk_ops interface must be implemented by the low-level driver. Currently only read and write are effectively used (by fatfs ). struct disk_ops { int ( *read )( uint8_t , uint32_t , void * , uint32_t ); int ( *write )( uint8_t , uint32_t , const void * , uint32_t ); int ( *ioctl )( uint8_t , uint32_t , void * ); SLIST_ENTRY ( disk_ops ) sc_next ; } Thread Safety All fs/fs functions are thread safe. Header Files All code which uses the fs/fs package needs to include the following header: #include \"fs/fs.h\" Data Structures All fs/fs data structures are opaque to client code. struct fs_file ; struct fs_dir ; struct fs_dirent ; API Functions in fs/fs that indicate success or failure do so with the following set of return codes: Return Codes The functions available in this OS feature are: Function Description fs_close Closes the specified file and invalidates the file handle. fs_closedir Closes the specified directory handle. fs_dirent_is_dir Tells you whether the specified directory entry is a sub-directory or a regular file. fs_dirent_name Retrieves the filename of the specified directory entry. fs_filelen Retrieves the current length of the specified open file. fs_getpos Retrieves the current read and write position of the specified open file. fs_mkdir Creates the directory represented by the specified path. fs_open Opens a file at the specified path. fs_opendir Opens the directory at the specified path. fs_read Reads data from the specified file. fs_readdir Reads the next entry in an open directory. fs_register Registers a file system with the abstraction layer. fs_rename Performs a rename and/or move of the specified source path to the specified destination. fs_seek Positions a file's read and write pointer at the specified offset. fs_unlink Unlinks the file or directory at the specified path. fs_write Writes the supplied data to the current offset of the specified file handle. Additional file system utilities that bundle some of the basic functions above are: Function Description fsutil_read_file Opens a file at the specified path, retrieve data from the file starting from the specified offset, and close the file and invalidate the file handle. fsutil_write_file Open a file at the specified path, write the supplied data to the current offset of the specified file handle, and close the file and invalidate the file handle.","title":"toc"},{"location":"os/modules/fs/fs/fs/#file-system-abstraction","text":"Mynewt provides a file system abstraction layer ( fs/fs ) to allow client code to be file system agnostic. By accessing the file system via the fs/fs API, client code can perform file system operations without being tied to a particular implementation. When possible, library code should use the fs/fs API rather than accessing the underlying file system directly.","title":"File System Abstraction"},{"location":"os/modules/fs/fs/fs/#description","text":"Applications should aim to minimize the amount of code which depends on a particular file system implementation. When possible, only depend on the fs/fs package. In terms of the Mynewt hierarchy, an app package must depend on a specific file system package, while library packages should only depend on fs/fs . Applications wanting to access a filesystem are required to include the necessary packages in their applications pkg.yml file. In the following example, the Newtron Flash File System is used. # repos/apache-mynewt-core/apps/slinky/pkg.yml pkg.name: repos/apache-mynewt-core/apps/slinky pkg.deps: - fs/fs # include the file operations interfaces - fs/nffs # include the NFFS filesystem implementation # repos/apache-mynewt-core/apps/slinky/syscfg.yml # [...] # Package: apps/<example app> # [...] CONFIG_NFFS: 1 # initialize and configure NFFS into the system # NFFS_DETECT_FAIL: 1 # Ignore NFFS detection issues # NFFS_DETECT_FAIL: 2 # Format a new NFFS file system on failure to detect # [...] Consult the documentation for nffs for a more detailed explanation of NFFS_DETECT_FAIL Code which uses the file system after the system has been initialized need only depend on fs/fs . For example, the libs/imgmgr package is a library which provides firmware upload and download functionality via the use of a file system. This library is only used after the system has been initialized, and therefore only depends on the fs/fs package. # repos/apache-mynewt-core/libs/imgmgr/pkg.yml pkg.name: libs/imgmgr pkg.deps: - fs/fs # [...] The libs/imgmgr package uses the fs/fs API for all file system operations.","title":"Description"},{"location":"os/modules/fs/fs/fs/#support-for-multiple-filesystems","text":"When using a single filesystem/disk, it is valid to provide paths in the standard unix way, eg, /<dir-name>/<file-name> . When trying to run more than one filesystem or a single filesystem in multiple devices simultaneosly, an extra name has to be given to the disk that is being used. The abstraction for that was added as the fs/disk package which is a dependency of fs/fs . It adds the following extra user function: int disk_register ( const char *disk_name , const char *fs_name , struct disk_ops *dops ) As an example os usage: disk_register ( \"mmc0\" , \"fatfs\" , &mmc_ops ); disk_register ( \"flash0\" , \"nffs\" , NULL ); This registers the name mmc0 to use fatfs as the filesystem and mmc_ops for the low-level disk driver and also registers flash0 to use nffs . nffs is currently strongly bound to the hal_flash interface, ignoring any other possible disk_ops given.","title":"Support for multiple filesystems"},{"location":"os/modules/fs/fs/fs/#struct-disk_ops","text":"To support a new low-level disk interface, the struct disk_ops interface must be implemented by the low-level driver. Currently only read and write are effectively used (by fatfs ). struct disk_ops { int ( *read )( uint8_t , uint32_t , void * , uint32_t ); int ( *write )( uint8_t , uint32_t , const void * , uint32_t ); int ( *ioctl )( uint8_t , uint32_t , void * ); SLIST_ENTRY ( disk_ops ) sc_next ; }","title":"struct disk_ops"},{"location":"os/modules/fs/fs/fs/#thread-safety","text":"All fs/fs functions are thread safe.","title":"Thread Safety"},{"location":"os/modules/fs/fs/fs/#header-files","text":"All code which uses the fs/fs package needs to include the following header: #include \"fs/fs.h\"","title":"Header Files"},{"location":"os/modules/fs/fs/fs/#data-structures","text":"All fs/fs data structures are opaque to client code. struct fs_file ; struct fs_dir ; struct fs_dirent ;","title":"Data Structures"},{"location":"os/modules/fs/fs/fs/#api","text":"Functions in fs/fs that indicate success or failure do so with the following set of return codes: Return Codes The functions available in this OS feature are: Function Description fs_close Closes the specified file and invalidates the file handle. fs_closedir Closes the specified directory handle. fs_dirent_is_dir Tells you whether the specified directory entry is a sub-directory or a regular file. fs_dirent_name Retrieves the filename of the specified directory entry. fs_filelen Retrieves the current length of the specified open file. fs_getpos Retrieves the current read and write position of the specified open file. fs_mkdir Creates the directory represented by the specified path. fs_open Opens a file at the specified path. fs_opendir Opens the directory at the specified path. fs_read Reads data from the specified file. fs_readdir Reads the next entry in an open directory. fs_register Registers a file system with the abstraction layer. fs_rename Performs a rename and/or move of the specified source path to the specified destination. fs_seek Positions a file's read and write pointer at the specified offset. fs_unlink Unlinks the file or directory at the specified path. fs_write Writes the supplied data to the current offset of the specified file handle. Additional file system utilities that bundle some of the basic functions above are: Function Description fsutil_read_file Opens a file at the specified path, retrieve data from the file starting from the specified offset, and close the file and invalidate the file handle. fsutil_write_file Open a file at the specified path, write the supplied data to the current offset of the specified file handle, and close the file and invalidate the file handle.","title":"API"},{"location":"os/modules/fs/fs/fs_close/","text":"fs_close int fs_close ( struct fs_file *file ) Closes the specified file and invalidates the file handle. Arguments Argument Description file Pointer to the file to close Returned values 0 on success FS error code on failure Notes If the file has already been unlinked, and the file has no other open handles, the fs_close() function causes the file to be deleted from the disk. Header file #include \"fs/fs.h\" Example The below code opens the file /settings/config.txt for reading, reads some data, and then closes the file. int read_config ( void ) { struct fs_file *file ; uint32_t bytes_read ; uint8_t buf [ 16 ]; int rc ; /* Open the file for reading. */ rc = fs_open ( \"/settings/config.txt\" , FS_ACCESS_READ , &file ); if ( rc != 0 ) { return -1 ; } /* Read up to 16 bytes from the file. */ rc = fs_read ( file , sizeof buf , buf , &bytes_read ); if ( rc == 0 ) { /* buf now contains up to 16 bytes of file data. */ console_printf ( \"read %u bytes\\n\" , bytes_read ) } /* Close the file. */ fs_close ( file ); return rc == 0 ? 0 : -1 ; }","title":"fs_close"},{"location":"os/modules/fs/fs/fs_close/#fs_close","text":"int fs_close ( struct fs_file *file ) Closes the specified file and invalidates the file handle.","title":"fs_close"},{"location":"os/modules/fs/fs/fs_close/#arguments","text":"Argument Description file Pointer to the file to close","title":"Arguments"},{"location":"os/modules/fs/fs/fs_close/#returned-values","text":"0 on success FS error code on failure","title":"Returned values"},{"location":"os/modules/fs/fs/fs_close/#notes","text":"If the file has already been unlinked, and the file has no other open handles, the fs_close() function causes the file to be deleted from the disk.","title":"Notes"},{"location":"os/modules/fs/fs/fs_close/#header-file","text":"#include \"fs/fs.h\"","title":"Header file"},{"location":"os/modules/fs/fs/fs_close/#example","text":"The below code opens the file /settings/config.txt for reading, reads some data, and then closes the file. int read_config ( void ) { struct fs_file *file ; uint32_t bytes_read ; uint8_t buf [ 16 ]; int rc ; /* Open the file for reading. */ rc = fs_open ( \"/settings/config.txt\" , FS_ACCESS_READ , &file ); if ( rc != 0 ) { return -1 ; } /* Read up to 16 bytes from the file. */ rc = fs_read ( file , sizeof buf , buf , &bytes_read ); if ( rc == 0 ) { /* buf now contains up to 16 bytes of file data. */ console_printf ( \"read %u bytes\\n\" , bytes_read ) } /* Close the file. */ fs_close ( file ); return rc == 0 ? 0 : -1 ; }","title":"Example"},{"location":"os/modules/fs/fs/fs_closedir/","text":"fs_closedir int fs_closedir ( struct fs_dir *dir ) Closes the specified directory handle. Arguments Argument Description dir The name of the directory to close Returned values 0 on success FS error code on failure Header file #include \"fs/fs.h\" Example This example iterates through the contents of a directory, printing the name of each child node. When the traversal is complete, the code closes the directory handle. int traverse_dir ( const char *dirname ) { struct fs_dirent *dirent ; struct fs_dir *dir ; char buf [ 64 ]; uint8_t name_len ; int rc ; rc = fs_opendir ( dirname , &dir ); if ( rc != 0 ) { return -1 ; } /* Iterate through the parent directory, printing the name of each child * entry. The loop only terminates via a function return. */ while ( 1 ) { /* Retrieve the next child node. */ rc = fs_readdir ( dir , &dirent ); if ( rc == FS_ENOENT ) { /* Traversal complete. */ return 0 ; } else if ( rc != 0 ) { /* Unexpected error. */ return -1 ; } /* Read the child node's name from the file system. */ rc = fs_dirent_name ( dirent , sizeof buf , buf , &name_len ); if ( rc != 0 ) { return -1 ; } /* Print the child node's name to the console. */ if ( fs_dirent_is_dir ( dirent )) { console_printf ( \" dir: \" ); } else { console_printf ( \"file: \" ); } console_printf ( \"%s\\n\" , buf ); } }","title":"fs_closedir"},{"location":"os/modules/fs/fs/fs_closedir/#fs_closedir","text":"int fs_closedir ( struct fs_dir *dir ) Closes the specified directory handle.","title":"fs_closedir"},{"location":"os/modules/fs/fs/fs_closedir/#arguments","text":"Argument Description dir The name of the directory to close","title":"Arguments"},{"location":"os/modules/fs/fs/fs_closedir/#returned-values","text":"0 on success FS error code on failure","title":"Returned values"},{"location":"os/modules/fs/fs/fs_closedir/#header-file","text":"#include \"fs/fs.h\"","title":"Header file"},{"location":"os/modules/fs/fs/fs_closedir/#example","text":"This example iterates through the contents of a directory, printing the name of each child node. When the traversal is complete, the code closes the directory handle. int traverse_dir ( const char *dirname ) { struct fs_dirent *dirent ; struct fs_dir *dir ; char buf [ 64 ]; uint8_t name_len ; int rc ; rc = fs_opendir ( dirname , &dir ); if ( rc != 0 ) { return -1 ; } /* Iterate through the parent directory, printing the name of each child * entry. The loop only terminates via a function return. */ while ( 1 ) { /* Retrieve the next child node. */ rc = fs_readdir ( dir , &dirent ); if ( rc == FS_ENOENT ) { /* Traversal complete. */ return 0 ; } else if ( rc != 0 ) { /* Unexpected error. */ return -1 ; } /* Read the child node's name from the file system. */ rc = fs_dirent_name ( dirent , sizeof buf , buf , &name_len ); if ( rc != 0 ) { return -1 ; } /* Print the child node's name to the console. */ if ( fs_dirent_is_dir ( dirent )) { console_printf ( \" dir: \" ); } else { console_printf ( \"file: \" ); } console_printf ( \"%s\\n\" , buf ); } }","title":"Example"},{"location":"os/modules/fs/fs/fs_dirent_is_dir/","text":"fs_dirent_is_dir int fs_dirent_is_dir ( const struct fs_dirent *dirent ) Tells you whether the specified directory entry is a sub-directory or a regular file. Arguments Argument Description dirent Pointer to the directory entry to query Returned values 1: The entry is a directory 0: The entry is a regular file. Header file #include \"fs/fs.h\" Example This example iterates through the contents of a directory, printing the name of each child node. When the traversal is complete, the code closes the directory handle. int traverse_dir ( const char *dirname ) { struct fs_dirent *dirent ; struct fs_dir *dir ; char buf [ 64 ]; uint8_t name_len ; int rc ; rc = fs_opendir ( dirname , &dir ); if ( rc != 0 ) { return -1 ; } /* Iterate through the parent directory, printing the name of each child * entry. The loop only terminates via a function return. */ while ( 1 ) { /* Retrieve the next child node. */ rc = fs_readdir ( dir , &dirent ); if ( rc == FS_ENOENT ) { /* Traversal complete. */ return 0 ; } else if ( rc != 0 ) { /* Unexpected error. */ return -1 ; } /* Read the child node's name from the file system. */ rc = fs_dirent_name ( dirent , sizeof buf , buf , &name_len ); if ( rc != 0 ) { return -1 ; } /* Print the child node's name to the console. */ if ( fs_dirent_is_dir ( dirent )) { console_printf ( \" dir: \" ); } else { console_printf ( \"file: \" ); } console_printf ( \"%s\\n\" , buf ); } }","title":"fs_dirent_is_dir"},{"location":"os/modules/fs/fs/fs_dirent_is_dir/#fs_dirent_is_dir","text":"int fs_dirent_is_dir ( const struct fs_dirent *dirent ) Tells you whether the specified directory entry is a sub-directory or a regular file.","title":"fs_dirent_is_dir"},{"location":"os/modules/fs/fs/fs_dirent_is_dir/#arguments","text":"Argument Description dirent Pointer to the directory entry to query","title":"Arguments"},{"location":"os/modules/fs/fs/fs_dirent_is_dir/#returned-values","text":"1: The entry is a directory 0: The entry is a regular file.","title":"Returned values"},{"location":"os/modules/fs/fs/fs_dirent_is_dir/#header-file","text":"#include \"fs/fs.h\"","title":"Header file"},{"location":"os/modules/fs/fs/fs_dirent_is_dir/#example","text":"This example iterates through the contents of a directory, printing the name of each child node. When the traversal is complete, the code closes the directory handle. int traverse_dir ( const char *dirname ) { struct fs_dirent *dirent ; struct fs_dir *dir ; char buf [ 64 ]; uint8_t name_len ; int rc ; rc = fs_opendir ( dirname , &dir ); if ( rc != 0 ) { return -1 ; } /* Iterate through the parent directory, printing the name of each child * entry. The loop only terminates via a function return. */ while ( 1 ) { /* Retrieve the next child node. */ rc = fs_readdir ( dir , &dirent ); if ( rc == FS_ENOENT ) { /* Traversal complete. */ return 0 ; } else if ( rc != 0 ) { /* Unexpected error. */ return -1 ; } /* Read the child node's name from the file system. */ rc = fs_dirent_name ( dirent , sizeof buf , buf , &name_len ); if ( rc != 0 ) { return -1 ; } /* Print the child node's name to the console. */ if ( fs_dirent_is_dir ( dirent )) { console_printf ( \" dir: \" ); } else { console_printf ( \"file: \" ); } console_printf ( \"%s\\n\" , buf ); } }","title":"Example"},{"location":"os/modules/fs/fs/fs_dirent_name/","text":"fs_dirent_name int fs_dirent_name ( const struct fs_dirent *dirent , size_t max_len , char *out_name , uint8_t *out_name_len ) Retrieves the filename of the specified directory entry. Arguments Argument Description dirent Pointer to the directory entry to query max_len Size of the \"out_name\" character buffer out_name On success, the entry's filename is written here; always null-terminated out_name_len On success, contains the actual length of the filename, NOT including the null-terminator Returned values 0 on success FS error code on failure Notes The retrieved filename is always null-terminated. To ensure enough space to hold the full filename plus a null-termintor, a destination buffer of size filename-max-length + 1 should be used. Header file #include \"fs/fs.h\" Example This example iterates through the contents of a directory, printing the name of each child node. When the traversal is complete, the code closes the directory handle. int traverse_dir ( const char *dirname ) { struct fs_dirent *dirent ; struct fs_dir *dir ; char buf [ 64 ]; uint8_t name_len ; int rc ; rc = fs_opendir ( dirname , &dir ); if ( rc != 0 ) { return -1 ; } /* Iterate through the parent directory, printing the name of each child * entry. The loop only terminates via a function return. */ while ( 1 ) { /* Retrieve the next child node. */ rc = fs_readdir ( dir , &dirent ); if ( rc == FS_ENOENT ) { /* Traversal complete. */ return 0 ; } else if ( rc != 0 ) { /* Unexpected error. */ return -1 ; } /* Read the child node's name from the file system. */ rc = fs_dirent_name ( dirent , sizeof buf , buf , &name_len ); if ( rc != 0 ) { return -1 ; } /* Print the child node's name to the console. */ if ( fs_dirent_is_dir ( dirent )) { console_printf ( \" dir: \" ); } else { console_printf ( \"file: \" ); } console_printf ( \"%s\\n\" , buf ); } }","title":"fs_dirent_name"},{"location":"os/modules/fs/fs/fs_dirent_name/#fs_dirent_name","text":"int fs_dirent_name ( const struct fs_dirent *dirent , size_t max_len , char *out_name , uint8_t *out_name_len ) Retrieves the filename of the specified directory entry.","title":"fs_dirent_name"},{"location":"os/modules/fs/fs/fs_dirent_name/#arguments","text":"Argument Description dirent Pointer to the directory entry to query max_len Size of the \"out_name\" character buffer out_name On success, the entry's filename is written here; always null-terminated out_name_len On success, contains the actual length of the filename, NOT including the null-terminator","title":"Arguments"},{"location":"os/modules/fs/fs/fs_dirent_name/#returned-values","text":"0 on success FS error code on failure","title":"Returned values"},{"location":"os/modules/fs/fs/fs_dirent_name/#notes","text":"The retrieved filename is always null-terminated. To ensure enough space to hold the full filename plus a null-termintor, a destination buffer of size filename-max-length + 1 should be used.","title":"Notes"},{"location":"os/modules/fs/fs/fs_dirent_name/#header-file","text":"#include \"fs/fs.h\"","title":"Header file"},{"location":"os/modules/fs/fs/fs_dirent_name/#example","text":"This example iterates through the contents of a directory, printing the name of each child node. When the traversal is complete, the code closes the directory handle. int traverse_dir ( const char *dirname ) { struct fs_dirent *dirent ; struct fs_dir *dir ; char buf [ 64 ]; uint8_t name_len ; int rc ; rc = fs_opendir ( dirname , &dir ); if ( rc != 0 ) { return -1 ; } /* Iterate through the parent directory, printing the name of each child * entry. The loop only terminates via a function return. */ while ( 1 ) { /* Retrieve the next child node. */ rc = fs_readdir ( dir , &dirent ); if ( rc == FS_ENOENT ) { /* Traversal complete. */ return 0 ; } else if ( rc != 0 ) { /* Unexpected error. */ return -1 ; } /* Read the child node's name from the file system. */ rc = fs_dirent_name ( dirent , sizeof buf , buf , &name_len ); if ( rc != 0 ) { return -1 ; } /* Print the child node's name to the console. */ if ( fs_dirent_is_dir ( dirent )) { console_printf ( \" dir: \" ); } else { console_printf ( \"file: \" ); } console_printf ( \"%s\\n\" , buf ); } }","title":"Example"},{"location":"os/modules/fs/fs/fs_filelen/","text":"fs_filelen int fs_filelen ( const struct fs_file *file , uint32_t *out_len ) Retrieves the current length of the specified open file. Arguments Argument Description file Pointer to the file to query out_len On success, the number of bytes in the file gets written here Returned values 0 on success FS error code on failure Header file #include \"fs/fs.h\" Example int write_config ( void ) { struct fs_file *file ; int rc ; /* If the file doesn't exist, create it. If it does exist, truncate it to * zero bytes. */ rc = fs_open ( \"/settings/config.txt\" , FS_ACCESS_WRITE | FS_ACCESS_TRUNCATE , &file ); if ( rc == 0 ) { /* Write 5 bytes of data to the file. */ rc = fs_write ( file , \"hello\" , 5 ); if ( rc == 0 ) { /* The file should now contain exactly five bytes. */ assert ( fs_filelen ( file ) == 5 ); } /* Close the file. */ fs_close ( file ); } return rc == 0 ? 0 : -1 ; }","title":"fs_filelen"},{"location":"os/modules/fs/fs/fs_filelen/#fs_filelen","text":"int fs_filelen ( const struct fs_file *file , uint32_t *out_len ) Retrieves the current length of the specified open file.","title":"fs_filelen"},{"location":"os/modules/fs/fs/fs_filelen/#arguments","text":"Argument Description file Pointer to the file to query out_len On success, the number of bytes in the file gets written here","title":"Arguments"},{"location":"os/modules/fs/fs/fs_filelen/#returned-values","text":"0 on success FS error code on failure","title":"Returned values"},{"location":"os/modules/fs/fs/fs_filelen/#header-file","text":"#include \"fs/fs.h\"","title":"Header file"},{"location":"os/modules/fs/fs/fs_filelen/#example","text":"int write_config ( void ) { struct fs_file *file ; int rc ; /* If the file doesn't exist, create it. If it does exist, truncate it to * zero bytes. */ rc = fs_open ( \"/settings/config.txt\" , FS_ACCESS_WRITE | FS_ACCESS_TRUNCATE , &file ); if ( rc == 0 ) { /* Write 5 bytes of data to the file. */ rc = fs_write ( file , \"hello\" , 5 ); if ( rc == 0 ) { /* The file should now contain exactly five bytes. */ assert ( fs_filelen ( file ) == 5 ); } /* Close the file. */ fs_close ( file ); } return rc == 0 ? 0 : -1 ; }","title":"Example"},{"location":"os/modules/fs/fs/fs_getpos/","text":"fs_getpos uint32_t fs_getpos ( const struct fs_file *file ) Retrieves the current read and write position of the specified open file. Arguments Argument Description file Pointer to the file to query Returned values The file offset, in bytes Notes If a file is opened in append mode, its write pointer is always positioned at the end of the file. Calling this function on such a file only indicates the read position. Header file #include \"fs/fs.h\"","title":"fs_getpos"},{"location":"os/modules/fs/fs/fs_getpos/#fs_getpos","text":"uint32_t fs_getpos ( const struct fs_file *file ) Retrieves the current read and write position of the specified open file.","title":"fs_getpos"},{"location":"os/modules/fs/fs/fs_getpos/#arguments","text":"Argument Description file Pointer to the file to query","title":"Arguments"},{"location":"os/modules/fs/fs/fs_getpos/#returned-values","text":"The file offset, in bytes","title":"Returned values"},{"location":"os/modules/fs/fs/fs_getpos/#notes","text":"If a file is opened in append mode, its write pointer is always positioned at the end of the file. Calling this function on such a file only indicates the read position.","title":"Notes"},{"location":"os/modules/fs/fs/fs_getpos/#header-file","text":"#include \"fs/fs.h\"","title":"Header file"},{"location":"os/modules/fs/fs/fs_mkdir/","text":"fs_mkdir int fs_mkdir ( const char *path ) Creates the directory represented by the specified path. Arguments Argument Description path The name of the directory to create Returned values 0 on success FS error code on failure. Notes All intermediate directories must already exist. The specified path must start with a '/' character. Header file #include \"fs/fs.h\" Example This example demonstrates creating a series of nested directories. int create_path ( void ) { int rc ; rc = fs_mkdir ( \"/data\" ); if ( rc != 0 ) goto err ; rc = fs_mkdir ( \"/data/logs\" ); if ( rc != 0 ) goto err ; rc = fs_mkdir ( \"/data/logs/temperature\" ); if ( rc != 0 ) goto err ; rc = fs_mkdir ( \"/data/logs/temperature/current\" ); if ( rc != 0 ) goto err ; return 0 ; err : /* Clean up the incomplete directory tree, if any. */ fs_unlink ( \"/data\" ); return -1 ; }","title":"fs_mkdir"},{"location":"os/modules/fs/fs/fs_mkdir/#fs_mkdir","text":"int fs_mkdir ( const char *path ) Creates the directory represented by the specified path.","title":"fs_mkdir"},{"location":"os/modules/fs/fs/fs_mkdir/#arguments","text":"Argument Description path The name of the directory to create","title":"Arguments"},{"location":"os/modules/fs/fs/fs_mkdir/#returned-values","text":"0 on success FS error code on failure.","title":"Returned values"},{"location":"os/modules/fs/fs/fs_mkdir/#notes","text":"All intermediate directories must already exist. The specified path must start with a '/' character.","title":"Notes"},{"location":"os/modules/fs/fs/fs_mkdir/#header-file","text":"#include \"fs/fs.h\"","title":"Header file"},{"location":"os/modules/fs/fs/fs_mkdir/#example","text":"This example demonstrates creating a series of nested directories. int create_path ( void ) { int rc ; rc = fs_mkdir ( \"/data\" ); if ( rc != 0 ) goto err ; rc = fs_mkdir ( \"/data/logs\" ); if ( rc != 0 ) goto err ; rc = fs_mkdir ( \"/data/logs/temperature\" ); if ( rc != 0 ) goto err ; rc = fs_mkdir ( \"/data/logs/temperature/current\" ); if ( rc != 0 ) goto err ; return 0 ; err : /* Clean up the incomplete directory tree, if any. */ fs_unlink ( \"/data\" ); return -1 ; }","title":"Example"},{"location":"os/modules/fs/fs/fs_open/","text":"fs_open int fs_open ( const char *filename , uint8_t access_flags , struct fs_file **out_file ) Opens a file at the specified path. The result of opening a nonexistent file depends on the access flags specified. All intermediate directories must already exist. The access flags are best understood by comparing them to their equivalent mode strings accepted by the C standard library function fopen() . The mode strings passed to fopen() map to fs_open() 's access flags as follows: \"r\" - FS_ACCESS_READ \"r+\" - FS_ACCESS_READ | FS_ACCESS_WRITE \"w\" - FS_ACCESS_WRITE | FS_ACCESS_TRUNCATE \"w+\" - FS_ACCESS_READ | FS_ACCESS_WRITE | FS_ACCESS_TRUNCATE \"a\" - FS_ACCESS_WRITE | FS_ACCESS_APPEND \"a+\" - FS_ACCESS_READ | FS_ACCESS_WRITE | FS_ACCESS_APPEND Arguments Argument Description filename Null-terminated string indicating the full path of the file to open access_flags Flags controlling file access; see above table out_file On success, a pointer to the newly-created file handle gets written here Returned values 0 on success FS error code on failure Notes There is no concept of current working directory. Therefore all file names should start with '/'. Always close files when you are done using them. If you forget to close a file, the file stays open forever. Do this too many times, and the underlying file system will run out of file handles, causing subsequent open operations to fail. This type of bug is known as a file handle leak or a file descriptor leak. Header file #include \"fs/fs.h\" Example The below code opens the file /settings/config.txt for reading, reads some data, and then closes the file. int read_config ( void ) { struct fs_file *file ; uint32_t bytes_read ; uint8_t buf [ 16 ]; int rc ; /* Open the file for reading. */ rc = fs_open ( \"/settings/config.txt\" , FS_ACCESS_READ , &file ); if ( rc != 0 ) { return -1 ; } /* Read up to 16 bytes from the file. */ rc = fs_read ( file , sizeof buf , buf , &bytes_read ); if ( rc == 0 ) { /* buf now contains up to 16 bytes of file data. */ console_printf ( \"read %u bytes\\n\" , bytes_read ) } /* Close the file. */ fs_close ( file ); return rc == 0 ? 0 : -1 ; }","title":"fs_open"},{"location":"os/modules/fs/fs/fs_open/#fs_open","text":"int fs_open ( const char *filename , uint8_t access_flags , struct fs_file **out_file ) Opens a file at the specified path. The result of opening a nonexistent file depends on the access flags specified. All intermediate directories must already exist. The access flags are best understood by comparing them to their equivalent mode strings accepted by the C standard library function fopen() . The mode strings passed to fopen() map to fs_open() 's access flags as follows: \"r\" - FS_ACCESS_READ \"r+\" - FS_ACCESS_READ | FS_ACCESS_WRITE \"w\" - FS_ACCESS_WRITE | FS_ACCESS_TRUNCATE \"w+\" - FS_ACCESS_READ | FS_ACCESS_WRITE | FS_ACCESS_TRUNCATE \"a\" - FS_ACCESS_WRITE | FS_ACCESS_APPEND \"a+\" - FS_ACCESS_READ | FS_ACCESS_WRITE | FS_ACCESS_APPEND","title":"fs_open"},{"location":"os/modules/fs/fs/fs_open/#arguments","text":"Argument Description filename Null-terminated string indicating the full path of the file to open access_flags Flags controlling file access; see above table out_file On success, a pointer to the newly-created file handle gets written here","title":"Arguments"},{"location":"os/modules/fs/fs/fs_open/#returned-values","text":"0 on success FS error code on failure","title":"Returned values"},{"location":"os/modules/fs/fs/fs_open/#notes","text":"There is no concept of current working directory. Therefore all file names should start with '/'. Always close files when you are done using them. If you forget to close a file, the file stays open forever. Do this too many times, and the underlying file system will run out of file handles, causing subsequent open operations to fail. This type of bug is known as a file handle leak or a file descriptor leak.","title":"Notes"},{"location":"os/modules/fs/fs/fs_open/#header-file","text":"#include \"fs/fs.h\"","title":"Header file"},{"location":"os/modules/fs/fs/fs_open/#example","text":"The below code opens the file /settings/config.txt for reading, reads some data, and then closes the file. int read_config ( void ) { struct fs_file *file ; uint32_t bytes_read ; uint8_t buf [ 16 ]; int rc ; /* Open the file for reading. */ rc = fs_open ( \"/settings/config.txt\" , FS_ACCESS_READ , &file ); if ( rc != 0 ) { return -1 ; } /* Read up to 16 bytes from the file. */ rc = fs_read ( file , sizeof buf , buf , &bytes_read ); if ( rc == 0 ) { /* buf now contains up to 16 bytes of file data. */ console_printf ( \"read %u bytes\\n\" , bytes_read ) } /* Close the file. */ fs_close ( file ); return rc == 0 ? 0 : -1 ; }","title":"Example"},{"location":"os/modules/fs/fs/fs_opendir/","text":"fs_opendir int fs_opendir ( const char *path , struct fs_dir **out_dir ) Opens the directory at the specified path. The directory's contents can be read with subsequent calls to fs_readdir(). When you are done with the directory handle, close it with fs_closedir(). Arguments Argument Description path The name of the directory to open out_dir On success, points to the directory handle Returned values 0 on success FS_ENOENT if the specified directory does not exist Other FS error code on error. Notes Unlinking files from the directory while it is open may result in unpredictable behavior during subsequent calls to fs_readdir() . New files can be created inside the directory without causing problems. Always close a directory when you are done reading from it. If you forget to close a directory, the directory stays open forever. Do this too many times, and the underlying file system will run out of directory handles, causing subsequent open operations to fail. This type of bug is known as a file handle leak or a file descriptor leak. Header file #include \"fs/fs.h\" Example This example iterates through the contents of a directory, printing the name of each child node. When the traversal is complete, the code closes the directory handle. int traverse_dir ( const char *dirname ) { struct fs_dirent *dirent ; struct fs_dir *dir ; char buf [ 64 ]; uint8_t name_len ; int rc ; rc = fs_opendir ( dirname , &dir ); if ( rc != 0 ) { return -1 ; } /* Iterate through the parent directory, printing the name of each child * entry. The loop only terminates via a function return. */ while ( 1 ) { /* Retrieve the next child node. */ rc = fs_readdir ( dir , &dirent ); if ( rc == FS_ENOENT ) { /* Traversal complete. */ return 0 ; } else if ( rc != 0 ) { /* Unexpected error. */ return -1 ; } /* Read the child node's name from the file system. */ rc = fs_dirent_name ( dirent , sizeof buf , buf , &name_len ); if ( rc != 0 ) { return -1 ; } /* Print the child node's name to the console. */ if ( fs_dirent_is_dir ( dirent )) { console_printf ( \" dir: \" ); } else { console_printf ( \"file: \" ); } console_printf ( \"%s\\n\" , buf ); } }","title":"fs_opendir"},{"location":"os/modules/fs/fs/fs_opendir/#fs_opendir","text":"int fs_opendir ( const char *path , struct fs_dir **out_dir ) Opens the directory at the specified path. The directory's contents can be read with subsequent calls to fs_readdir(). When you are done with the directory handle, close it with fs_closedir().","title":"fs_opendir"},{"location":"os/modules/fs/fs/fs_opendir/#arguments","text":"Argument Description path The name of the directory to open out_dir On success, points to the directory handle","title":"Arguments"},{"location":"os/modules/fs/fs/fs_opendir/#returned-values","text":"0 on success FS_ENOENT if the specified directory does not exist Other FS error code on error.","title":"Returned values"},{"location":"os/modules/fs/fs/fs_opendir/#notes","text":"Unlinking files from the directory while it is open may result in unpredictable behavior during subsequent calls to fs_readdir() . New files can be created inside the directory without causing problems. Always close a directory when you are done reading from it. If you forget to close a directory, the directory stays open forever. Do this too many times, and the underlying file system will run out of directory handles, causing subsequent open operations to fail. This type of bug is known as a file handle leak or a file descriptor leak.","title":"Notes"},{"location":"os/modules/fs/fs/fs_opendir/#header-file","text":"#include \"fs/fs.h\"","title":"Header file"},{"location":"os/modules/fs/fs/fs_opendir/#example","text":"This example iterates through the contents of a directory, printing the name of each child node. When the traversal is complete, the code closes the directory handle. int traverse_dir ( const char *dirname ) { struct fs_dirent *dirent ; struct fs_dir *dir ; char buf [ 64 ]; uint8_t name_len ; int rc ; rc = fs_opendir ( dirname , &dir ); if ( rc != 0 ) { return -1 ; } /* Iterate through the parent directory, printing the name of each child * entry. The loop only terminates via a function return. */ while ( 1 ) { /* Retrieve the next child node. */ rc = fs_readdir ( dir , &dirent ); if ( rc == FS_ENOENT ) { /* Traversal complete. */ return 0 ; } else if ( rc != 0 ) { /* Unexpected error. */ return -1 ; } /* Read the child node's name from the file system. */ rc = fs_dirent_name ( dirent , sizeof buf , buf , &name_len ); if ( rc != 0 ) { return -1 ; } /* Print the child node's name to the console. */ if ( fs_dirent_is_dir ( dirent )) { console_printf ( \" dir: \" ); } else { console_printf ( \"file: \" ); } console_printf ( \"%s\\n\" , buf ); } }","title":"Example"},{"location":"os/modules/fs/fs/fs_ops/","text":"struct fs_ops struct fs_ops { int ( *f_open )( const char *filename , uint8_t access_flags , struct fs_file **out_file ); int ( *f_close )( struct fs_file *file ); int ( *f_read )( struct fs_file *file , uint32_t len , void *out_data , uint32_t *out_len ); int ( *f_write )( struct fs_file *file , const void *data , int len ); int ( *f_seek )( struct fs_file *file , uint32_t offset ); uint32_t ( *f_getpos )( const struct fs_file *file ); int ( *f_filelen )( const struct fs_file *file , uint32_t *out_len ); int ( *f_unlink )( const char *filename ); int ( *f_rename )( const char *from , const char *to ); int ( *f_mkdir )( const char *path ); int ( *f_opendir )( const char *path , struct fs_dir **out_dir ); int ( *f_readdir )( struct fs_dir *dir , struct fs_dirent **out_dirent ); int ( *f_closedir )( struct fs_dir *dir ); int ( *f_dirent_name )( const struct fs_dirent *dirent , size_t max_len , char *out_name , uint8_t *out_name_len ); int ( *f_dirent_is_dir )( const struct fs_dirent *dirent ); const char *f_name ; }; This data structure consists of a set of function pointers. Each function pointer corresponds to a file system operation. When registering a file system with the abstraction layer, each function pointer must be pointed at the corresponding routine in the custom file system package. The required behavior of each corresponding function is documented in the file system abstraction layer API . Header file #include \"fs/fs_if.h\"","title":"struct fs_ops"},{"location":"os/modules/fs/fs/fs_ops/#struct-fs_ops","text":"struct fs_ops { int ( *f_open )( const char *filename , uint8_t access_flags , struct fs_file **out_file ); int ( *f_close )( struct fs_file *file ); int ( *f_read )( struct fs_file *file , uint32_t len , void *out_data , uint32_t *out_len ); int ( *f_write )( struct fs_file *file , const void *data , int len ); int ( *f_seek )( struct fs_file *file , uint32_t offset ); uint32_t ( *f_getpos )( const struct fs_file *file ); int ( *f_filelen )( const struct fs_file *file , uint32_t *out_len ); int ( *f_unlink )( const char *filename ); int ( *f_rename )( const char *from , const char *to ); int ( *f_mkdir )( const char *path ); int ( *f_opendir )( const char *path , struct fs_dir **out_dir ); int ( *f_readdir )( struct fs_dir *dir , struct fs_dirent **out_dirent ); int ( *f_closedir )( struct fs_dir *dir ); int ( *f_dirent_name )( const struct fs_dirent *dirent , size_t max_len , char *out_name , uint8_t *out_name_len ); int ( *f_dirent_is_dir )( const struct fs_dirent *dirent ); const char *f_name ; }; This data structure consists of a set of function pointers. Each function pointer corresponds to a file system operation. When registering a file system with the abstraction layer, each function pointer must be pointed at the corresponding routine in the custom file system package. The required behavior of each corresponding function is documented in the file system abstraction layer API .","title":"struct fs_ops"},{"location":"os/modules/fs/fs/fs_ops/#header-file","text":"#include \"fs/fs_if.h\"","title":"Header file"},{"location":"os/modules/fs/fs/fs_read/","text":"fs_read int fs_read ( struct fs_file *file , uint32_t len , void *out_data , uint32_t *out_len ) Reads data from the specified file. If more data is requested than remains in the file, all available data is retrieved and a success code is returned. Arguments Argument Description file Pointer to the the file to read from len The number of bytes to attempt to read out_data The destination buffer to read into out_len On success, the number of bytes actually read gets written here. Pass null if you don't care. Returned values 0 on success FS error code on failure Header file #include \"fs/fs.h\" Example The below code opens the file /settings/config.txt for reading, reads some data, and then closes the file. int read_config ( void ) { struct fs_file *file ; uint32_t bytes_read ; uint8_t buf [ 16 ]; int rc ; /* Open the file for reading. */ rc = fs_open ( \"/settings/config.txt\" , FS_ACCESS_READ , &file ); if ( rc != 0 ) { return -1 ; } /* Read up to 16 bytes from the file. */ rc = fs_read ( file , sizeof buf , buf , &bytes_read ); if ( rc == 0 ) { /* buf now contains up to 16 bytes of file data. */ console_printf ( \"read %u bytes\\n\" , bytes_read ) } /* Close the file. */ fs_close ( file ); return rc == 0 ? 0 : -1 ; }","title":"fs_read"},{"location":"os/modules/fs/fs/fs_read/#fs_read","text":"int fs_read ( struct fs_file *file , uint32_t len , void *out_data , uint32_t *out_len ) Reads data from the specified file. If more data is requested than remains in the file, all available data is retrieved and a success code is returned.","title":"fs_read"},{"location":"os/modules/fs/fs/fs_read/#arguments","text":"Argument Description file Pointer to the the file to read from len The number of bytes to attempt to read out_data The destination buffer to read into out_len On success, the number of bytes actually read gets written here. Pass null if you don't care.","title":"Arguments"},{"location":"os/modules/fs/fs/fs_read/#returned-values","text":"0 on success FS error code on failure","title":"Returned values"},{"location":"os/modules/fs/fs/fs_read/#header-file","text":"#include \"fs/fs.h\"","title":"Header file"},{"location":"os/modules/fs/fs/fs_read/#example","text":"The below code opens the file /settings/config.txt for reading, reads some data, and then closes the file. int read_config ( void ) { struct fs_file *file ; uint32_t bytes_read ; uint8_t buf [ 16 ]; int rc ; /* Open the file for reading. */ rc = fs_open ( \"/settings/config.txt\" , FS_ACCESS_READ , &file ); if ( rc != 0 ) { return -1 ; } /* Read up to 16 bytes from the file. */ rc = fs_read ( file , sizeof buf , buf , &bytes_read ); if ( rc == 0 ) { /* buf now contains up to 16 bytes of file data. */ console_printf ( \"read %u bytes\\n\" , bytes_read ) } /* Close the file. */ fs_close ( file ); return rc == 0 ? 0 : -1 ; }","title":"Example"},{"location":"os/modules/fs/fs/fs_readdir/","text":"fs_readdir int fs_readdir ( struct fs_dir *dir , struct fs_dirent **out_dirent ); Reads the next entry in an open directory. Arguments Argument Description dir The directory handle to read from out_dirent On success, points to the next child entry in the specified directory Returned values 0 on success FS_ENOENT if there are no more entries in the parent directory Other FS error code on error. Header file #include \"fs/fs.h\" Example This example iterates through the contents of a directory, printing the name of each child node. When the traversal is complete, the code closes the directory handle. int traverse_dir ( const char *dirname ) { struct fs_dirent *dirent ; struct fs_dir *dir ; char buf [ 64 ]; uint8_t name_len ; int rc ; rc = fs_opendir ( dirname , &dir ); if ( rc != 0 ) { return -1 ; } /* Iterate through the parent directory, printing the name of each child * entry. The loop only terminates via a function return. */ while ( 1 ) { /* Retrieve the next child node. */ rc = fs_readdir ( dir , &dirent ); if ( rc == FS_ENOENT ) { /* Traversal complete. */ return 0 ; } else if ( rc != 0 ) { /* Unexpected error. */ return -1 ; } /* Read the child node's name from the file system. */ rc = fs_dirent_name ( dirent , sizeof buf , buf , &name_len ); if ( rc != 0 ) { return -1 ; } /* Print the child node's name to the console. */ if ( fs_dirent_is_dir ( dirent )) { console_printf ( \" dir: \" ); } else { console_printf ( \"file: \" ); } console_printf ( \"%s\\n\" , buf ); } }","title":"fs_readdir"},{"location":"os/modules/fs/fs/fs_readdir/#fs_readdir","text":"int fs_readdir ( struct fs_dir *dir , struct fs_dirent **out_dirent ); Reads the next entry in an open directory.","title":"fs_readdir"},{"location":"os/modules/fs/fs/fs_readdir/#arguments","text":"Argument Description dir The directory handle to read from out_dirent On success, points to the next child entry in the specified directory","title":"Arguments"},{"location":"os/modules/fs/fs/fs_readdir/#returned-values","text":"0 on success FS_ENOENT if there are no more entries in the parent directory Other FS error code on error.","title":"Returned values"},{"location":"os/modules/fs/fs/fs_readdir/#header-file","text":"#include \"fs/fs.h\"","title":"Header file"},{"location":"os/modules/fs/fs/fs_readdir/#example","text":"This example iterates through the contents of a directory, printing the name of each child node. When the traversal is complete, the code closes the directory handle. int traverse_dir ( const char *dirname ) { struct fs_dirent *dirent ; struct fs_dir *dir ; char buf [ 64 ]; uint8_t name_len ; int rc ; rc = fs_opendir ( dirname , &dir ); if ( rc != 0 ) { return -1 ; } /* Iterate through the parent directory, printing the name of each child * entry. The loop only terminates via a function return. */ while ( 1 ) { /* Retrieve the next child node. */ rc = fs_readdir ( dir , &dirent ); if ( rc == FS_ENOENT ) { /* Traversal complete. */ return 0 ; } else if ( rc != 0 ) { /* Unexpected error. */ return -1 ; } /* Read the child node's name from the file system. */ rc = fs_dirent_name ( dirent , sizeof buf , buf , &name_len ); if ( rc != 0 ) { return -1 ; } /* Print the child node's name to the console. */ if ( fs_dirent_is_dir ( dirent )) { console_printf ( \" dir: \" ); } else { console_printf ( \"file: \" ); } console_printf ( \"%s\\n\" , buf ); } }","title":"Example"},{"location":"os/modules/fs/fs/fs_register/","text":"fs_register int fs_register ( const struct fs_ops *fops ) Registers a file system with the abstraction layer. On success, all calls into fs/fs will use the registered file system. Arguments Argument Description fops A pointer to const struct fs_ops . Specifies which file system routines get mapped to the fs/fs API. All function pointers must be filled in. Returned values 0 on success FS_EEXIST if a file system has already been registered Notes Only one file system can be registered. The registered file system is mounted in the root directory ( / ). Header file #include \"fs/fs.h\"","title":"fs_register"},{"location":"os/modules/fs/fs/fs_register/#fs_register","text":"int fs_register ( const struct fs_ops *fops ) Registers a file system with the abstraction layer. On success, all calls into fs/fs will use the registered file system.","title":"fs_register"},{"location":"os/modules/fs/fs/fs_register/#arguments","text":"Argument Description fops A pointer to const struct fs_ops . Specifies which file system routines get mapped to the fs/fs API. All function pointers must be filled in.","title":"Arguments"},{"location":"os/modules/fs/fs/fs_register/#returned-values","text":"0 on success FS_EEXIST if a file system has already been registered","title":"Returned values"},{"location":"os/modules/fs/fs/fs_register/#notes","text":"Only one file system can be registered. The registered file system is mounted in the root directory ( / ).","title":"Notes"},{"location":"os/modules/fs/fs/fs_register/#header-file","text":"#include \"fs/fs.h\"","title":"Header file"},{"location":"os/modules/fs/fs/fs_rename/","text":"fs_rename int fs_rename ( const char *from , const char *to ) Performs a rename and / or move of the specified source path to the specified destination. The source path can refer to a file or a directory. Arguments Argument Description from The source path to The destination path Returned values 0 on success FS error code on failure Notes The source path can refer to either a file or a directory. All intermediate directories in the destination path must already exist. If the source path refers to a file, the destination path must contain a full filename path, rather than just the new parent directory. If an object already exists at the specified destination path, this function causes it to be unlinked prior to the rename (i.e., the destination gets clobbered). Header file #include \"fs/fs.h\" Example This example demonstrates how to use fs_rename() to perform a log rotation. In this example, there is one primary log and three archived logs. FS_ENOENT errors returned by fs_rename() are ignored; it is not an error if an archived log was never created. int rotate_logs ( void ) { struct fs_file *file ; int rc ; /* Rotate each of the log files. */ rc = fs_rename ( \"/var/log/messages.2\" , \"/var/log/messages.3\" ) if ( rc != 0 && rc != FS_ENOENT ) return -1 ; rc = fs_rename ( \"/var/log/messages.1\" , \"/var/log/messages.2\" ) if ( rc != 0 && rc != FS_ENOENT ) return -1 ; rc = fs_rename ( \"/var/log/messages.0\" , \"/var/log/messages.1\" ) if ( rc != 0 && rc != FS_ENOENT ) return -1 ; rc = fs_rename ( \"/var/log/messages\" , \"/var/log/messages.0\" ) if ( rc != 0 && rc != FS_ENOENT ) return -1 ; /* Now create the new log file. */ rc = fs_open ( \"/var/log/messages\" , FS_ACCESS_WRITE | FS_ACCESS_TRUNCATE , &file ); if ( rc != 0 ) return -1 ; rc = fs_write ( file , \"Creating new log file.\\n\" , 23 ); fs_close ( file ); return rc == 0 ? 0 : -1 ; }","title":"fs_rename"},{"location":"os/modules/fs/fs/fs_rename/#fs_rename","text":"int fs_rename ( const char *from , const char *to ) Performs a rename and / or move of the specified source path to the specified destination. The source path can refer to a file or a directory.","title":"fs_rename"},{"location":"os/modules/fs/fs/fs_rename/#arguments","text":"Argument Description from The source path to The destination path","title":"Arguments"},{"location":"os/modules/fs/fs/fs_rename/#returned-values","text":"0 on success FS error code on failure","title":"Returned values"},{"location":"os/modules/fs/fs/fs_rename/#notes","text":"The source path can refer to either a file or a directory. All intermediate directories in the destination path must already exist. If the source path refers to a file, the destination path must contain a full filename path, rather than just the new parent directory. If an object already exists at the specified destination path, this function causes it to be unlinked prior to the rename (i.e., the destination gets clobbered).","title":"Notes"},{"location":"os/modules/fs/fs/fs_rename/#header-file","text":"#include \"fs/fs.h\"","title":"Header file"},{"location":"os/modules/fs/fs/fs_rename/#example","text":"This example demonstrates how to use fs_rename() to perform a log rotation. In this example, there is one primary log and three archived logs. FS_ENOENT errors returned by fs_rename() are ignored; it is not an error if an archived log was never created. int rotate_logs ( void ) { struct fs_file *file ; int rc ; /* Rotate each of the log files. */ rc = fs_rename ( \"/var/log/messages.2\" , \"/var/log/messages.3\" ) if ( rc != 0 && rc != FS_ENOENT ) return -1 ; rc = fs_rename ( \"/var/log/messages.1\" , \"/var/log/messages.2\" ) if ( rc != 0 && rc != FS_ENOENT ) return -1 ; rc = fs_rename ( \"/var/log/messages.0\" , \"/var/log/messages.1\" ) if ( rc != 0 && rc != FS_ENOENT ) return -1 ; rc = fs_rename ( \"/var/log/messages\" , \"/var/log/messages.0\" ) if ( rc != 0 && rc != FS_ENOENT ) return -1 ; /* Now create the new log file. */ rc = fs_open ( \"/var/log/messages\" , FS_ACCESS_WRITE | FS_ACCESS_TRUNCATE , &file ); if ( rc != 0 ) return -1 ; rc = fs_write ( file , \"Creating new log file.\\n\" , 23 ); fs_close ( file ); return rc == 0 ? 0 : -1 ; }","title":"Example"},{"location":"os/modules/fs/fs/fs_return_codes/","text":"fs/fs Return Codes Functions in fs/fs that indicate success or failure do so with the following set of return codes: Return code Description FS_EOK Success FS_ECORRUPT File system corrupt FS_EHW Error accessing storage medium FS_EOFFSET Invalid offset FS_EINVAL Invalid argument FS_ENOMEM Insufficient memory FS_ENOENT No such file or directory FS_EEMPTY Specified region is empty (internal only) FS_EFULL Disk full FS_EUNEXP Disk contains unexpected metadata FS_EOS OS error FS_EEXIST File or directory already exists FS_EACCESS Operation prohibited by file open mode FS_EUNINIT File system not initialized Header file #include \"fs/fs.h\"","title":"Return Codes"},{"location":"os/modules/fs/fs/fs_return_codes/#fsfs-return-codes","text":"Functions in fs/fs that indicate success or failure do so with the following set of return codes: Return code Description FS_EOK Success FS_ECORRUPT File system corrupt FS_EHW Error accessing storage medium FS_EOFFSET Invalid offset FS_EINVAL Invalid argument FS_ENOMEM Insufficient memory FS_ENOENT No such file or directory FS_EEMPTY Specified region is empty (internal only) FS_EFULL Disk full FS_EUNEXP Disk contains unexpected metadata FS_EOS OS error FS_EEXIST File or directory already exists FS_EACCESS Operation prohibited by file open mode FS_EUNINIT File system not initialized","title":"fs/fs Return Codes"},{"location":"os/modules/fs/fs/fs_return_codes/#header-file","text":"#include \"fs/fs.h\"","title":"Header file"},{"location":"os/modules/fs/fs/fs_seek/","text":"fs_seek int fs_seek ( struct fs_file *file , uint32_t offset ) Positions a file's read and write pointer at the specified offset. The offset is expressed as the number of bytes from the start of the file (i.e., seeking to offset 0 places the pointer at the first byte in the file). Arguments Argument Description file Pointer to the file to reposition offset The 0-based file offset to seek to Returned values 0 on success FS error code on failure Notes If a file is opened in append mode, its write pointer is always positioned at the end of the file. Calling this function on such a file only affects the read pointer. Header file #include \"fs/fs.h\" Example The following example reads four bytes from a file, starting at an offset of eight. int read_part1_middle ( void ) { struct fs_file *file ; uint32_t bytes_read ; uint8_t buf [ 4 ]; int rc ; rc = fs_open ( \"/data/parts/1.bin\" , FS_ACCESS_READ , &file ); if ( rc == 0 ) { /* Advance to offset 8. */ rc = fs_seek ( file , 8 ); if ( rc == 0 ) { /* Read bytes 8, 9, 10, and 11. */ rc = fs_read ( file , 4 , buf , &bytes_read ); if ( rc == 0 ) { /* buf now contains up to 4 bytes of file data. */ console_printf ( \"read %u bytes\\n\" , bytes_read ) } } /* Close the file. */ fs_close ( file ); } return rc == 0 ? 0 : -1 ; }","title":"fs_seek"},{"location":"os/modules/fs/fs/fs_seek/#fs_seek","text":"int fs_seek ( struct fs_file *file , uint32_t offset ) Positions a file's read and write pointer at the specified offset. The offset is expressed as the number of bytes from the start of the file (i.e., seeking to offset 0 places the pointer at the first byte in the file).","title":"fs_seek"},{"location":"os/modules/fs/fs/fs_seek/#arguments","text":"Argument Description file Pointer to the file to reposition offset The 0-based file offset to seek to","title":"Arguments"},{"location":"os/modules/fs/fs/fs_seek/#returned-values","text":"0 on success FS error code on failure","title":"Returned values"},{"location":"os/modules/fs/fs/fs_seek/#notes","text":"If a file is opened in append mode, its write pointer is always positioned at the end of the file. Calling this function on such a file only affects the read pointer.","title":"Notes"},{"location":"os/modules/fs/fs/fs_seek/#header-file","text":"#include \"fs/fs.h\"","title":"Header file"},{"location":"os/modules/fs/fs/fs_seek/#example","text":"The following example reads four bytes from a file, starting at an offset of eight. int read_part1_middle ( void ) { struct fs_file *file ; uint32_t bytes_read ; uint8_t buf [ 4 ]; int rc ; rc = fs_open ( \"/data/parts/1.bin\" , FS_ACCESS_READ , &file ); if ( rc == 0 ) { /* Advance to offset 8. */ rc = fs_seek ( file , 8 ); if ( rc == 0 ) { /* Read bytes 8, 9, 10, and 11. */ rc = fs_read ( file , 4 , buf , &bytes_read ); if ( rc == 0 ) { /* buf now contains up to 4 bytes of file data. */ console_printf ( \"read %u bytes\\n\" , bytes_read ) } } /* Close the file. */ fs_close ( file ); } return rc == 0 ? 0 : -1 ; }","title":"Example"},{"location":"os/modules/fs/fs/fs_unlink/","text":"fs_unlink int fs_unlink ( const char *filename ) Unlinks the file or directory at the specified path. This is the function to use if you want to delete a file or directory from the disk. If the path refers to a directory, all the directory's descendants are recursively unlinked. Any open file handles referring to an unlinked file remain valid, and can be read from and written to as long as they remain open. Arguments Argument Description filename The path of the file or directory to unlink Returned values 0 on success FS error code on failure Header file #include \"fs/fs.h\" Example The following example creates a file and then immediately unlinks it. By unlinking the file, this function prevents other OS tasks from accessing it. When the function closes the file, it is deleted from the disk. int process_data ( void ) { struct fs_file *file ; int rc ; /* If the file doesn't exist, create it. If it does exist, truncate it to * zero bytes. */ rc = fs_open ( \"/tmp/buffer.bin\" , FS_ACCESS_WRITE | FS_ACCESS_TRUNCATE , &file ); if ( rc == 0 ) { /* Unlink the file so that other tasks cannot access it. */ fs_unlink ( \"/tmp/buffer.bin\" ) /* <use the file as a data buffer> */ /* Close the file. This operation causes the file to be deleted from * the disk because it was unlinked earlier (and it has no other open * file handles). */ fs_close ( file ); } return rc == 0 ? 0 : -1 ; }","title":"fs_unlink"},{"location":"os/modules/fs/fs/fs_unlink/#fs_unlink","text":"int fs_unlink ( const char *filename ) Unlinks the file or directory at the specified path. This is the function to use if you want to delete a file or directory from the disk. If the path refers to a directory, all the directory's descendants are recursively unlinked. Any open file handles referring to an unlinked file remain valid, and can be read from and written to as long as they remain open.","title":"fs_unlink"},{"location":"os/modules/fs/fs/fs_unlink/#arguments","text":"Argument Description filename The path of the file or directory to unlink","title":"Arguments"},{"location":"os/modules/fs/fs/fs_unlink/#returned-values","text":"0 on success FS error code on failure","title":"Returned values"},{"location":"os/modules/fs/fs/fs_unlink/#header-file","text":"#include \"fs/fs.h\"","title":"Header file"},{"location":"os/modules/fs/fs/fs_unlink/#example","text":"The following example creates a file and then immediately unlinks it. By unlinking the file, this function prevents other OS tasks from accessing it. When the function closes the file, it is deleted from the disk. int process_data ( void ) { struct fs_file *file ; int rc ; /* If the file doesn't exist, create it. If it does exist, truncate it to * zero bytes. */ rc = fs_open ( \"/tmp/buffer.bin\" , FS_ACCESS_WRITE | FS_ACCESS_TRUNCATE , &file ); if ( rc == 0 ) { /* Unlink the file so that other tasks cannot access it. */ fs_unlink ( \"/tmp/buffer.bin\" ) /* <use the file as a data buffer> */ /* Close the file. This operation causes the file to be deleted from * the disk because it was unlinked earlier (and it has no other open * file handles). */ fs_close ( file ); } return rc == 0 ? 0 : -1 ; }","title":"Example"},{"location":"os/modules/fs/fs/fs_write/","text":"fs_write int fs_write ( struct fs_file *file , const void *data , int len ) Writes the supplied data to the current offset of the specified file handle. Arguments Argument Description file Pointer to the file to write to data The data to write len The number of bytes to write Returned values 0 on success FS error code on failure Notes For files opened in append mode, the specified data is always written to the end. Header file #include \"fs/fs.h\" Example int write_config ( void ) { struct fs_file *file ; int rc ; /* If the file doesn't exist, create it. If it does exist, truncate it to * zero bytes. */ rc = fs_open ( \"/settings/config.txt\" , FS_ACCESS_WRITE | FS_ACCESS_TRUNCATE , &file ); if ( rc == 0 ) { /* Write 5 bytes of data to the file. */ rc = fs_write ( file , \"hello\" , 5 ); if ( rc == 0 ) { /* The file should now contain exactly five bytes. */ assert ( fs_filelen ( file ) == 5 ); } /* Close the file. */ fs_close ( file ); } return rc == 0 ? 0 : -1 ; }","title":"fs_write"},{"location":"os/modules/fs/fs/fs_write/#fs_write","text":"int fs_write ( struct fs_file *file , const void *data , int len ) Writes the supplied data to the current offset of the specified file handle.","title":"fs_write"},{"location":"os/modules/fs/fs/fs_write/#arguments","text":"Argument Description file Pointer to the file to write to data The data to write len The number of bytes to write","title":"Arguments"},{"location":"os/modules/fs/fs/fs_write/#returned-values","text":"0 on success FS error code on failure","title":"Returned values"},{"location":"os/modules/fs/fs/fs_write/#notes","text":"For files opened in append mode, the specified data is always written to the end.","title":"Notes"},{"location":"os/modules/fs/fs/fs_write/#header-file","text":"#include \"fs/fs.h\"","title":"Header file"},{"location":"os/modules/fs/fs/fs_write/#example","text":"int write_config ( void ) { struct fs_file *file ; int rc ; /* If the file doesn't exist, create it. If it does exist, truncate it to * zero bytes. */ rc = fs_open ( \"/settings/config.txt\" , FS_ACCESS_WRITE | FS_ACCESS_TRUNCATE , &file ); if ( rc == 0 ) { /* Write 5 bytes of data to the file. */ rc = fs_write ( file , \"hello\" , 5 ); if ( rc == 0 ) { /* The file should now contain exactly five bytes. */ assert ( fs_filelen ( file ) == 5 ); } /* Close the file. */ fs_close ( file ); } return rc == 0 ? 0 : -1 ; }","title":"Example"},{"location":"os/modules/fs/fs/fsutil_read_file/","text":"fsutil_read_file int fsutil_read_file ( const char *path , uint32_t offset , uint32_t len , void *dst , uint32_t *out_len ) Calls fs_open(), fs_read(), and fs_close() to open a file at the specified path, retrieve data from the file starting from the specified offset, and close the file and invalidate the file handle. Arguments Argument Description path Pointer to the directory entry to query offset Position of the file's read pointer len Number of bytes to attempt to read dst Destination buffer to read into out_len On success, the number of bytes actually read gets written here. Pass null if you don't care. Returned values 0 on success FS error code on failure Notes This is a convenience function. It is useful when the amount of data to be read from the file is small (i.e., all the data read can easily fit in a single buffer). Header file #include \"fs/fs.h\" Example This example demonstrates reading a small text file in its entirety and printing its contents to the console. int print_status ( void ) { uint32_t bytes_read ; uint8_t buf [ 16 ]; int rc ; /* Read up to 15 bytes from the start of the file. */ rc = fsutil_read_file ( \"/cfg/status.txt\" , 0 , sizeof buf - 1 , buf , &bytes_read ); if ( rc != 0 ) return -1 ; /* Null-terminate the string just read. */ buf [ bytes_read ] = '\\0' ; /* Print the file contents to the console. */ console_printf ( \"%s\\n\" , buf ); return 0 ; }","title":"fsutil_read_file"},{"location":"os/modules/fs/fs/fsutil_read_file/#fsutil_read_file","text":"int fsutil_read_file ( const char *path , uint32_t offset , uint32_t len , void *dst , uint32_t *out_len ) Calls fs_open(), fs_read(), and fs_close() to open a file at the specified path, retrieve data from the file starting from the specified offset, and close the file and invalidate the file handle.","title":"fsutil_read_file"},{"location":"os/modules/fs/fs/fsutil_read_file/#arguments","text":"Argument Description path Pointer to the directory entry to query offset Position of the file's read pointer len Number of bytes to attempt to read dst Destination buffer to read into out_len On success, the number of bytes actually read gets written here. Pass null if you don't care.","title":"Arguments"},{"location":"os/modules/fs/fs/fsutil_read_file/#returned-values","text":"0 on success FS error code on failure","title":"Returned values"},{"location":"os/modules/fs/fs/fsutil_read_file/#notes","text":"This is a convenience function. It is useful when the amount of data to be read from the file is small (i.e., all the data read can easily fit in a single buffer).","title":"Notes"},{"location":"os/modules/fs/fs/fsutil_read_file/#header-file","text":"#include \"fs/fs.h\"","title":"Header file"},{"location":"os/modules/fs/fs/fsutil_read_file/#example","text":"This example demonstrates reading a small text file in its entirety and printing its contents to the console. int print_status ( void ) { uint32_t bytes_read ; uint8_t buf [ 16 ]; int rc ; /* Read up to 15 bytes from the start of the file. */ rc = fsutil_read_file ( \"/cfg/status.txt\" , 0 , sizeof buf - 1 , buf , &bytes_read ); if ( rc != 0 ) return -1 ; /* Null-terminate the string just read. */ buf [ bytes_read ] = '\\0' ; /* Print the file contents to the console. */ console_printf ( \"%s\\n\" , buf ); return 0 ; }","title":"Example"},{"location":"os/modules/fs/fs/fsutil_write_file/","text":"fsutil_write_file int fsutil_write_file ( const char *path , const void *data , uint32_t len ) Calls fs_open(), fs_write(), and fs_close() to open a file at the specified path, write the supplied data to the current offset of the specified file handle, and close the file and invalidate the file handle. If the specified file already exists, it is truncated and overwritten with the specified data. Arguments Argument Description path Pointer to the file to write to data The data to write len The number of bytes to write Returned values 0 on success FS error code on failure Header file #include \"fs/fs.h\" Example This example creates a 4-byte file. int write_id ( void ) { int rc ; /* Create the parent directory. */ rc = fs_mkdir ( \"/cfg\" ); if ( rc != 0 && rc != FS_EALREADY ) { return -1 ; } /* Create a file and write four bytes to it. */ rc = fsutil_write_file ( \"/cfg/id.txt\" , \"1234\" , 4 ); if ( rc != 0 ) { return -1 ; } return 0 ; }","title":"fsutil_write_file"},{"location":"os/modules/fs/fs/fsutil_write_file/#fsutil_write_file","text":"int fsutil_write_file ( const char *path , const void *data , uint32_t len ) Calls fs_open(), fs_write(), and fs_close() to open a file at the specified path, write the supplied data to the current offset of the specified file handle, and close the file and invalidate the file handle. If the specified file already exists, it is truncated and overwritten with the specified data.","title":"fsutil_write_file"},{"location":"os/modules/fs/fs/fsutil_write_file/#arguments","text":"Argument Description path Pointer to the file to write to data The data to write len The number of bytes to write","title":"Arguments"},{"location":"os/modules/fs/fs/fsutil_write_file/#returned-values","text":"0 on success FS error code on failure","title":"Returned values"},{"location":"os/modules/fs/fs/fsutil_write_file/#header-file","text":"#include \"fs/fs.h\"","title":"Header file"},{"location":"os/modules/fs/fs/fsutil_write_file/#example","text":"This example creates a 4-byte file. int write_id ( void ) { int rc ; /* Create the parent directory. */ rc = fs_mkdir ( \"/cfg\" ); if ( rc != 0 && rc != FS_EALREADY ) { return -1 ; } /* Create a file and write four bytes to it. */ rc = fsutil_write_file ( \"/cfg/id.txt\" , \"1234\" , 4 ); if ( rc != 0 ) { return -1 ; } return 0 ; }","title":"Example"},{"location":"os/modules/fs/nffs/nffs/","text":"Newtron Flash Filesystem (nffs) Mynewt includes the Newtron Flash File System (nffs). This file system is designed with two priorities that makes it suitable for embedded use: Minimal RAM usage Reliability Mynewt also provides an abstraction layer API (fs) to allow you to swap out nffs with a different file system of your choice. Description Areas At the top level, an nffs disk is partitioned into areas . An area is a region of disk with the following properties: An area can be fully erased without affecting any other areas. Writing to one area does not restrict writes to other areas. Regarding property 1: Generally, flash hardware divides its memory space into \"blocks.\" When erasing flash, entire blocks must be erased in a single operation; partial erases are not possible. Regarding property 2: Furthermore, some flash hardware imposes a restriction with regards to writes: writes within a block must be strictly sequential. For example, if you wish to write to the first 16 bytes of a block, you must write bytes 1 through 15 before writing byte 16. This restriction only applies at the block level; writes to one block have no effect on what parts of other blocks can be written. Thus, each area must comprise a discrete number of blocks. Initialization As part of overall system initialization, mynewt re-initialized the filesystem as follows: Restores an existing file system via detection. Creates a new file system via formatting. A typical initialization sequence is the following: Detect an nffs file system in a specific region of flash. If no file system was detected, if configured to do so, format a new file system in the same flash region. Note that in the latter case, the behavior is controlled with a variable in the syscfg.yml file. If NFFS_DETECT_FAIL is set to 1, the system ignores NFFS filesystem detection issues, but unless a new filesystem is formatted manually, all filesystem access will fail. If NFFS_DETECT_FAIL is set to 2, the system will format a new filesystem - note however this effectively deletes all existing data in the NFFS flash areas. Both methods require the user to describe how the flash memory should be divided into nffs areas. This is accomplished with an array of struct nffs_area_desc configured as part of the BSP configureation. After nffs has been initialized, the application can access the file system via the file system abstraction layer . Data Structures The fs/nffs package exposes the following data structures: Struct Description struct nffs_area_desc Descriptor for a single nffs area. struct nffs_config Configuration struct for nffs. API The functions available in this OS feature are: Function Description nffs_detect Searches for a valid nffs file system among the specified areas. nffs_format Erases all the specified areas and initializes them with a clean nffs file system. nffs_init Initializes internal nffs memory and data structures. Miscellaneous measures RAM usage: 24 bytes per inode 12 bytes per data block 36 bytes per inode cache entry 32 bytes per data block cache entry Maximum filename size: 256 characters (no null terminator required) Disallowed filename characters: '/' and '\\0' Internals nffs implementation details can be found here: nffs_internals Future enhancements Error correction. Encryption. Compression.","title":"toc"},{"location":"os/modules/fs/nffs/nffs/#newtron-flash-filesystem-nffs","text":"Mynewt includes the Newtron Flash File System (nffs). This file system is designed with two priorities that makes it suitable for embedded use: Minimal RAM usage Reliability Mynewt also provides an abstraction layer API (fs) to allow you to swap out nffs with a different file system of your choice.","title":"Newtron Flash Filesystem (nffs)"},{"location":"os/modules/fs/nffs/nffs/#description","text":"","title":"Description"},{"location":"os/modules/fs/nffs/nffs/#areas","text":"At the top level, an nffs disk is partitioned into areas . An area is a region of disk with the following properties: An area can be fully erased without affecting any other areas. Writing to one area does not restrict writes to other areas. Regarding property 1: Generally, flash hardware divides its memory space into \"blocks.\" When erasing flash, entire blocks must be erased in a single operation; partial erases are not possible. Regarding property 2: Furthermore, some flash hardware imposes a restriction with regards to writes: writes within a block must be strictly sequential. For example, if you wish to write to the first 16 bytes of a block, you must write bytes 1 through 15 before writing byte 16. This restriction only applies at the block level; writes to one block have no effect on what parts of other blocks can be written. Thus, each area must comprise a discrete number of blocks.","title":"Areas"},{"location":"os/modules/fs/nffs/nffs/#initialization","text":"As part of overall system initialization, mynewt re-initialized the filesystem as follows: Restores an existing file system via detection. Creates a new file system via formatting. A typical initialization sequence is the following: Detect an nffs file system in a specific region of flash. If no file system was detected, if configured to do so, format a new file system in the same flash region. Note that in the latter case, the behavior is controlled with a variable in the syscfg.yml file. If NFFS_DETECT_FAIL is set to 1, the system ignores NFFS filesystem detection issues, but unless a new filesystem is formatted manually, all filesystem access will fail. If NFFS_DETECT_FAIL is set to 2, the system will format a new filesystem - note however this effectively deletes all existing data in the NFFS flash areas. Both methods require the user to describe how the flash memory should be divided into nffs areas. This is accomplished with an array of struct nffs_area_desc configured as part of the BSP configureation. After nffs has been initialized, the application can access the file system via the file system abstraction layer .","title":"Initialization"},{"location":"os/modules/fs/nffs/nffs/#data-structures","text":"The fs/nffs package exposes the following data structures: Struct Description struct nffs_area_desc Descriptor for a single nffs area. struct nffs_config Configuration struct for nffs.","title":"Data Structures"},{"location":"os/modules/fs/nffs/nffs/#api","text":"The functions available in this OS feature are: Function Description nffs_detect Searches for a valid nffs file system among the specified areas. nffs_format Erases all the specified areas and initializes them with a clean nffs file system. nffs_init Initializes internal nffs memory and data structures.","title":"API"},{"location":"os/modules/fs/nffs/nffs/#miscellaneous-measures","text":"RAM usage: 24 bytes per inode 12 bytes per data block 36 bytes per inode cache entry 32 bytes per data block cache entry Maximum filename size: 256 characters (no null terminator required) Disallowed filename characters: '/' and '\\0'","title":"Miscellaneous measures"},{"location":"os/modules/fs/nffs/nffs/#internals","text":"nffs implementation details can be found here: nffs_internals","title":"Internals"},{"location":"os/modules/fs/nffs/nffs/#future-enhancements","text":"Error correction. Encryption. Compression.","title":"Future enhancements"},{"location":"os/modules/fs/nffs/nffs_area_desc/","text":"struct nffs_area_desc struct nffs_area_desc { uint32_t nad_offset ; /* Flash offset of start of area. */ uint32_t nad_length ; /* Size of area, in bytes. */ uint8_t nad_flash_id ; /* Logical flash id */ }; Descriptor for a single nffs area. An area is a region of disk with the following properties: An area can be fully erased without affecting any other areas. Writing to one area does not restrict writes to other areas. Regarding property 1: Generally, flash hardware divides its memory space into \"blocks.\" When erasing flash, entire blocks must be erased in a single operation; partial erases are not possible. Regarding property 2: Furthermore, some flash hardware imposes a restriction with regards to writes: writes within a block must be strictly sequential. For example, if you wish to write to the first 16 bytes of a block, you must write bytes 1 through 15 before writing byte 16. This restriction only applies at the block level; writes to one block have no effect on what parts of other blocks can be written. Thus, each area must comprise a discrete number of blocks. An array of area descriptors is terminated by an entry with a nad_length value of 0. Notes Typically, a product's flash layout is exposed via its BSP-specific bsp_flash_dev() function. This function retrieves the layout of the specified flash device resident in the BSP. The result of this function can then be converted into the struct nffs_area_desc[] that nffs requires. Header file #include \"nffs/nffs.h\"","title":"struct nffs_area_desc"},{"location":"os/modules/fs/nffs/nffs_area_desc/#struct-nffs_area_desc","text":"struct nffs_area_desc { uint32_t nad_offset ; /* Flash offset of start of area. */ uint32_t nad_length ; /* Size of area, in bytes. */ uint8_t nad_flash_id ; /* Logical flash id */ }; Descriptor for a single nffs area. An area is a region of disk with the following properties: An area can be fully erased without affecting any other areas. Writing to one area does not restrict writes to other areas. Regarding property 1: Generally, flash hardware divides its memory space into \"blocks.\" When erasing flash, entire blocks must be erased in a single operation; partial erases are not possible. Regarding property 2: Furthermore, some flash hardware imposes a restriction with regards to writes: writes within a block must be strictly sequential. For example, if you wish to write to the first 16 bytes of a block, you must write bytes 1 through 15 before writing byte 16. This restriction only applies at the block level; writes to one block have no effect on what parts of other blocks can be written. Thus, each area must comprise a discrete number of blocks. An array of area descriptors is terminated by an entry with a nad_length value of 0.","title":"struct nffs_area_desc"},{"location":"os/modules/fs/nffs/nffs_area_desc/#notes","text":"Typically, a product's flash layout is exposed via its BSP-specific bsp_flash_dev() function. This function retrieves the layout of the specified flash device resident in the BSP. The result of this function can then be converted into the struct nffs_area_desc[] that nffs requires.","title":"Notes"},{"location":"os/modules/fs/nffs/nffs_area_desc/#header-file","text":"#include \"nffs/nffs.h\"","title":"Header file"},{"location":"os/modules/fs/nffs/nffs_config/","text":"struct nffs_config struct nffs_config { /** Maximum number of inodes; default=1024. */ uint32_t nc_num_inodes ; /** Maximum number of data blocks; default=4096. */ uint32_t nc_num_blocks ; /** Maximum number of open files; default=4. */ uint32_t nc_num_files ; /** Inode cache size; default=4. */ uint32_t nc_num_cache_inodes ; /** Data block cache size; default=64. */ uint32_t nc_num_cache_blocks ; }; The file system is configured by populating fields in a global struct nffs_config instance. Each field in the structure corresponds to a setting. All configuration must be done prior to calling nffs_init(). Any fields that are set to 0 (or not set at all) inherit the corresponding default value. This means that it is impossible to configure any setting with a value of zero. Notes The global struct nffs_config instance is exposed in nffs/nffs.h as follows: extern struct nffs_config nffs_config ; Header file #include \"nffs/nffs.h\"","title":"struct nffs_config"},{"location":"os/modules/fs/nffs/nffs_config/#struct-nffs_config","text":"struct nffs_config { /** Maximum number of inodes; default=1024. */ uint32_t nc_num_inodes ; /** Maximum number of data blocks; default=4096. */ uint32_t nc_num_blocks ; /** Maximum number of open files; default=4. */ uint32_t nc_num_files ; /** Inode cache size; default=4. */ uint32_t nc_num_cache_inodes ; /** Data block cache size; default=64. */ uint32_t nc_num_cache_blocks ; }; The file system is configured by populating fields in a global struct nffs_config instance. Each field in the structure corresponds to a setting. All configuration must be done prior to calling nffs_init(). Any fields that are set to 0 (or not set at all) inherit the corresponding default value. This means that it is impossible to configure any setting with a value of zero.","title":"struct nffs_config"},{"location":"os/modules/fs/nffs/nffs_config/#notes","text":"The global struct nffs_config instance is exposed in nffs/nffs.h as follows: extern struct nffs_config nffs_config ;","title":"Notes"},{"location":"os/modules/fs/nffs/nffs_config/#header-file","text":"#include \"nffs/nffs.h\"","title":"Header file"},{"location":"os/modules/fs/nffs/nffs_detect/","text":"nffs_detect int nffs_detect ( const struct nffs_area_desc *area_descs ) Searches for a valid nffs file system among the specified areas. This function succeeds if a file system is detected among any subset of the supplied areas. If the area set does not contain a valid file system, a new one can be created via a separate call to nffs_format(). Arguments Argument Description area_descs The set of areas to search. This array must be terminated with a 0-length area. Returned values 0 on success FS_ECORRUPT if no valid file system was detected Other FS error code on failure Header file #include \"nffs/nffs.h\" Example /*** hw/hal/include/hal/flash_map.h */ /* * Flash area types */ #define FLASH_AREA_BOOTLOADER 0 #define FLASH_AREA_IMAGE_0 1 #define FLASH_AREA_IMAGE_1 2 #define FLASH_AREA_IMAGE_SCRATCH 3 #define FLASH_AREA_NFFS 4 /*** project/slinky/src/main.c */ int main ( int argc , char **argv ) { int rc ; int cnt ; /* NFFS_AREA_MAX is defined in the BSP-specified bsp.h header file. */ struct nffs_area_desc descs [ NFFS_AREA_MAX ]; /* Initialize nffs's internal state. */ rc = nffs_init (); assert ( rc == 0 ); /* Convert the set of flash blocks we intend to use for nffs into an array * of nffs area descriptors. */ cnt = NFFS_AREA_MAX ; rc = flash_area_to_nffs_desc ( FLASH_AREA_NFFS , &cnt , descs ); assert ( rc == 0 ); /* Attempt to restore an existing nffs file system from flash. */ if ( nffs_detect ( descs ) == FS_ECORRUPT ) { /* No valid nffs instance detected; format a new one. */ rc = nffs_format ( descs ); assert ( rc == 0 ); } /* [ ... ] */ }","title":"nffs_detect"},{"location":"os/modules/fs/nffs/nffs_detect/#nffs_detect","text":"int nffs_detect ( const struct nffs_area_desc *area_descs ) Searches for a valid nffs file system among the specified areas. This function succeeds if a file system is detected among any subset of the supplied areas. If the area set does not contain a valid file system, a new one can be created via a separate call to nffs_format().","title":"nffs_detect"},{"location":"os/modules/fs/nffs/nffs_detect/#arguments","text":"Argument Description area_descs The set of areas to search. This array must be terminated with a 0-length area.","title":"Arguments"},{"location":"os/modules/fs/nffs/nffs_detect/#returned-values","text":"0 on success FS_ECORRUPT if no valid file system was detected Other FS error code on failure","title":"Returned values"},{"location":"os/modules/fs/nffs/nffs_detect/#header-file","text":"#include \"nffs/nffs.h\"","title":"Header file"},{"location":"os/modules/fs/nffs/nffs_detect/#example","text":"/*** hw/hal/include/hal/flash_map.h */ /* * Flash area types */ #define FLASH_AREA_BOOTLOADER 0 #define FLASH_AREA_IMAGE_0 1 #define FLASH_AREA_IMAGE_1 2 #define FLASH_AREA_IMAGE_SCRATCH 3 #define FLASH_AREA_NFFS 4 /*** project/slinky/src/main.c */ int main ( int argc , char **argv ) { int rc ; int cnt ; /* NFFS_AREA_MAX is defined in the BSP-specified bsp.h header file. */ struct nffs_area_desc descs [ NFFS_AREA_MAX ]; /* Initialize nffs's internal state. */ rc = nffs_init (); assert ( rc == 0 ); /* Convert the set of flash blocks we intend to use for nffs into an array * of nffs area descriptors. */ cnt = NFFS_AREA_MAX ; rc = flash_area_to_nffs_desc ( FLASH_AREA_NFFS , &cnt , descs ); assert ( rc == 0 ); /* Attempt to restore an existing nffs file system from flash. */ if ( nffs_detect ( descs ) == FS_ECORRUPT ) { /* No valid nffs instance detected; format a new one. */ rc = nffs_format ( descs ); assert ( rc == 0 ); } /* [ ... ] */ }","title":"Example"},{"location":"os/modules/fs/nffs/nffs_format/","text":"nffs_format int nffs_format ( const struct nffs_area_desc *area_descs ) Erases all the specified areas and initializes them with a clean nffs file system. Arguments Argument Description area_descs The set of areas to format Returned values 0 on success FS error code on failure. Header file #include \"nffs/nffs.h\" Example /*** hw/hal/include/hal/flash_map.h */ /* * Flash area types */ #define FLASH_AREA_BOOTLOADER 0 #define FLASH_AREA_IMAGE_0 1 #define FLASH_AREA_IMAGE_1 2 #define FLASH_AREA_IMAGE_SCRATCH 3 #define FLASH_AREA_NFFS 4 /*** project/slinky/src/main.c */ int main ( int argc , char **argv ) { int rc ; int cnt ; /* NFFS_AREA_MAX is defined in the BSP-specified bsp.h header file. */ struct nffs_area_desc descs [ NFFS_AREA_MAX ]; /* Initialize nffs's internal state. */ rc = nffs_init (); assert ( rc == 0 ); /* Convert the set of flash blocks we intend to use for nffs into an array * of nffs area descriptors. */ cnt = NFFS_AREA_MAX ; rc = flash_area_to_nffs_desc ( FLASH_AREA_NFFS , &cnt , descs ); assert ( rc == 0 ); /* Attempt to restore an existing nffs file system from flash. */ if ( nffs_detect ( descs ) == FS_ECORRUPT ) { /* No valid nffs instance detected; format a new one. */ rc = nffs_format ( descs ); assert ( rc == 0 ); } /* [ ... ] */ }","title":"nffs_format"},{"location":"os/modules/fs/nffs/nffs_format/#nffs_format","text":"int nffs_format ( const struct nffs_area_desc *area_descs ) Erases all the specified areas and initializes them with a clean nffs file system.","title":"nffs_format"},{"location":"os/modules/fs/nffs/nffs_format/#arguments","text":"Argument Description area_descs The set of areas to format","title":"Arguments"},{"location":"os/modules/fs/nffs/nffs_format/#returned-values","text":"0 on success FS error code on failure.","title":"Returned values"},{"location":"os/modules/fs/nffs/nffs_format/#header-file","text":"#include \"nffs/nffs.h\"","title":"Header file"},{"location":"os/modules/fs/nffs/nffs_format/#example","text":"/*** hw/hal/include/hal/flash_map.h */ /* * Flash area types */ #define FLASH_AREA_BOOTLOADER 0 #define FLASH_AREA_IMAGE_0 1 #define FLASH_AREA_IMAGE_1 2 #define FLASH_AREA_IMAGE_SCRATCH 3 #define FLASH_AREA_NFFS 4 /*** project/slinky/src/main.c */ int main ( int argc , char **argv ) { int rc ; int cnt ; /* NFFS_AREA_MAX is defined in the BSP-specified bsp.h header file. */ struct nffs_area_desc descs [ NFFS_AREA_MAX ]; /* Initialize nffs's internal state. */ rc = nffs_init (); assert ( rc == 0 ); /* Convert the set of flash blocks we intend to use for nffs into an array * of nffs area descriptors. */ cnt = NFFS_AREA_MAX ; rc = flash_area_to_nffs_desc ( FLASH_AREA_NFFS , &cnt , descs ); assert ( rc == 0 ); /* Attempt to restore an existing nffs file system from flash. */ if ( nffs_detect ( descs ) == FS_ECORRUPT ) { /* No valid nffs instance detected; format a new one. */ rc = nffs_format ( descs ); assert ( rc == 0 ); } /* [ ... ] */ }","title":"Example"},{"location":"os/modules/fs/nffs/nffs_init/","text":"nffs_init int nffs_init ( void ) Initializes internal nffs memory and data structures. This must be called before any nffs operations are attempted. Returned values 0 on success FS error code on failure Header file #include \"nffs/nffs.h\"","title":"nffs_init"},{"location":"os/modules/fs/nffs/nffs_init/#nffs_init","text":"int nffs_init ( void ) Initializes internal nffs memory and data structures. This must be called before any nffs operations are attempted.","title":"nffs_init"},{"location":"os/modules/fs/nffs/nffs_init/#returned-values","text":"0 on success FS error code on failure","title":"Returned values"},{"location":"os/modules/fs/nffs/nffs_init/#header-file","text":"#include \"nffs/nffs.h\"","title":"Header file"},{"location":"os/modules/fs/nffs/nffs_internals/","text":"Internals of nffs Disk structure On disk, each area is prefixed with the following header: /** On-disk representation of an area header. */ struct nffs_disk_area { uint32_t nda_magic [ 4 ]; /* NFFS_AREA_MAGIC{0,1,2,3} */ uint32_t nda_length ; /* Total size of area, in bytes. */ uint8_t nda_ver ; /* Current nffs version: 0 */ uint8_t nda_gc_seq ; /* Garbage collection count. */ uint8_t reserved8 ; uint8_t nda_id ; /* 0xff if scratch area. */ }; Beyond its header, an area contains a sequence of disk objects, representing the contents of the file system. There are two types of objects: inodes and data blocks . An inode represents a file or directory; a data block represents part of a file's contents. /** On-disk representation of an inode (file or directory). */ struct nffs_disk_inode { uint32_t ndi_magic ; /* NFFS_INODE_MAGIC */ uint32_t ndi_id ; /* Unique object ID. */ uint32_t ndi_seq ; /* Sequence number; greater supersedes lesser. */ uint32_t ndi_parent_id ; /* Object ID of parent directory inode. */ uint8_t reserved8 ; uint8_t ndi_filename_len ; /* Length of filename, in bytes. */ uint16_t ndi_crc16 ; /* Covers rest of header and filename. */ /* Followed by filename. */ }; An inode filename's length cannot exceed 256 bytes. The filename is not null-terminated. The following ASCII characters are not allowed in a filename: / (slash character) \\0 (NUL character) /** On-disk representation of a data block. */ struct nffs_disk_block { uint32_t ndb_magic ; /* NFFS_BLOCK_MAGIC */ uint32_t ndb_id ; /* Unique object ID. */ uint32_t ndb_seq ; /* Sequence number; greater supersedes lesser. */ uint32_t ndb_inode_id ; /* Object ID of owning inode. */ uint32_t ndb_prev_id ; /* Object ID of previous block in file; NFFS_ID_NONE if this is the first block. */ uint16_t ndb_data_len ; /* Length of data contents, in bytes. */ uint16_t ndb_crc16 ; /* Covers rest of header and data. */ /* Followed by 'ndb_data_len' bytes of data. */ }; Each data block contains the ID of the previous data block in the file. Together, the set of blocks in a file form a reverse singly-linked list. The maximum number of data bytes that a block can contain is determined at initialization-time. The result is the greatest number which satisfies all of the following restrictions: No more than 2048. At least two maximum-sized blocks can fit in the smallest area. The 2048 number was chosen somewhat arbitrarily, and may change in the future. ID space All disk objects have a unique 32-bit ID. The ID space is partitioned as follows: ID range Node type 0x00000000 - 0x0fffffff Directory inodes 0x10000000 - 0x7fffffff File inodes 0x80000000 - 0xfffffffe Data blocks 0xffffffff Reserved (NFFS_ID_NONE) Scratch area A valid nffs file system must contain a single \"scratch area.\" The scratch area does not contain any objects of its own, and is only used during garbage collection. The scratch area must have a size greater than or equal to each of the other areas in flash. RAM representation Every object in the file system is stored in a 256-entry hash table. An object's hash key is derived from its 32-bit ID. Each list in the hash table is sorted by time of use; most-recently-used is at the front of the list. All objects are represented by the following structure: /** * What gets stored in the hash table. Each entry represents a data block or * an inode. */ struct nffs_hash_entry { SLIST_ENTRY ( nffs_hash_entry ) nhe_next ; uint32_t nhe_id ; /* 0 - 0x7fffffff if inode; else if block. */ uint32_t nhe_flash_loc ; /* Upper-byte = area idx; rest = area offset. */ }; For each data block, the above structure is all that is stored in RAM. To acquire more information about a data block, the block header must be read from flash. Inodes require a fuller RAM representation to capture the structure of the file system. There are two types of inodes: files and directories . Each inode hash entry is actually an instance of the following structure: /** Each inode hash entry is actually one of these. */ struct nffs_inode_entry { struct nffs_hash_entry nie_hash_entry ; SLIST_ENTRY ( nffs_inode_entry ) nie_sibling_next ; union { struct nffs_inode_list nie_child_list ; /* If directory */ struct nffs_hash_entry *nie_last_block_entry ; /* If file */ }; uint8_t nie_refcnt ; }; A directory inode contains a list of its child files and directories ( fie_child_list ). These entries are sorted alphabetically using the ASCII character set. A file inode contains a pointer to the last data block in the file ( nie_last_block_entry ). For most file operations, the reversed block list must be walked backwards. This introduces a number of speed inefficiencies: All data blocks must be read to determine the length of the file. Data blocks often need to be processed sequentially. The reversed nature of the block list transforms this from linear time to an O(n^2) operation. Furthermore, obtaining information about any constituent data block requires a separate flash read. Inode cache and Data Block cache The speed issues are addressed by a pair of caches. Cached inodes entries contain the file length and a much more convenient doubly-linked list of cached data blocks. The benefit of using caches is that the size of the caches need not be proportional to the size of the file system. In other words, caches can address speed efficiency concerns without negatively impacting the file system's scalability. nffs requires both caches during normal operation, so it is not possible to disable them. However, the cache sizes are configurable, and both caches can be configured with a size of one if RAM usage must be minimized. The following data structures are used in the inode and data block caches. /** Full data block representation; not stored permanently in RAM. */ struct nffs_block { struct nffs_hash_entry *nb_hash_entry ; /* Points to real block entry. */ uint32_t nb_seq ; /* Sequence number; greater supersedes lesser. */ struct nffs_inode_entry *nb_inode_entry ; /* Owning inode. */ struct nffs_hash_entry *nb_prev ; /* Previous block in file. */ uint16_t nb_data_len ; /* # of data bytes in block. */ uint16_t reserved16 ; }; /** Represents a single cached data block. */ struct nffs_cache_block { TAILQ_ENTRY ( nffs_cache_block ) ncb_link ; /* Next / prev cached block. */ struct nffs_block ncb_block ; /* Full data block. */ uint32_t ncb_file_offset ; /* File offset of this block. */ }; /** Full inode representation; not stored permanently in RAM. */ struct nffs_inode { struct nffs_inode_entry *ni_inode_entry ; /* Points to real inode entry. */ uint32_t ni_seq ; /* Sequence number; greater supersedes lesser. */ struct nffs_inode_entry *ni_parent ; /* Points to parent directory. */ uint8_t ni_filename_len ; /* # chars in filename. */ uint8_t ni_filename [ NFFS_SHORT_FILENAME_LEN ]; /* First 3 bytes. */ }; /** Doubly-linked tail queue of cached blocks; contained in cached inodes. */ TAILQ_HEAD ( nffs_block_cache_list , nffs_block_cache_entry ); /** Represents a single cached file inode. */ struct nffs_cache_inode { TAILQ_ENTRY ( nffs_cache_inode ) nci_link ; /* Sorted; LRU at tail. */ struct nffs_inode nci_inode ; /* Full inode. */ struct nffs_cache_block_list nci_block_list ; /* List of cached blocks. */ uint32_t nci_file_size ; /* Total file size. */ }; Only file inodes are cached; directory inodes are never cached. Within a cached inode, all cached data blocks are contiguous. E.g., if the start and end of a file are cached, then the middle must also be cached. A data block is only cached if its owning file is also cached. Internally, cached inodes are stored in a singly-linked list, ordered by time of use. The most-recently-used entry is the first element in the list. If a new inode needs to be cached, but the inode cache is full, the least-recently-used entry is freed to make room for the new one. The following operations cause an inode to be cached: Querying a file's length. Seeking within a file. Reading from a file. Writing to a file. The following operations cause a data block to be cached: Reading from the block. Writing to the block. If one of the above operations is applied to a data block that is not currently cached, nffs uses the following procedure to cache the necessary block: If none of the owning inode's blocks are currently cached, allocate a cached block entry corresponding to the requested block and insert it into the inode's list. Else if the requested file offset is less than that of the first cached block, bridge the gap between the inode's sequence of cached blocks and the block that now needs to be cached. This is accomplished by caching each block in the gap, finishing with the requested block. Else (the requested offset is beyond the end of the cache), If the requested offset belongs to the block that immediately follows the end of the cache, cache the block and append it to the list. Else, clear the cache, and populate it with the single entry corresponding to the requested block. If the system is unable to allocate a cached block entry at any point during the above procedure, the system frees up other blocks currently in the cache. This is accomplished as follows: Iterate the inode cache in reverse (i.e., start with the least-recently-used entry). For each entry: If the entry's cached block list is empty, advance to the next entry. Else, free all the cached blocks in the entry's list. Because the system imposes a minimum block cache size of one, the above procedure will always reclaim at least one cache block entry. The above procedure may result in the freeing of the block list that belongs to the very inode being operated on. This is OK, as the final block to get cached is always the block being requested. Detection The file system detection process consists of scanning a specified set of flash regions for valid nffs areas, and then populating the RAM representation of the file system with the detected objects. Detection is initiated with the nffs_detect() function. Not every area descriptor passed to nffs_detect() needs to reference a valid nffs area. Detection is successful as long as a complete file system is detected somewhere in the specified regions of flash. If an application is unsure where a file system might be located, it can initiate detection across the entire flash region. A detected file system is valid if: At least one non-scratch area is present. At least one scratch area is present (only the first gets used if there is more than one). The root directory inode is present. During detection, each indicated region of flash is checked for a valid area header. The contents of each valid non-scratch area are then restored into the nffs RAM representation. The following procedure is applied to each object in the area: Verify the object's integrity via a crc16 check. If invalid, the object is discarded and the procedure restarts on the next object in the area. Convert the disk object into its corresponding RAM representation and insert it into the hash table. If the object is an inode, its reference count is initialized to 1, indicating ownership by its parent directory. If an object with the same ID is already present, then one supersedes the other. Accept the object with the greater sequence number and discard the other. If the object references a nonexistent inode (parent directory in the case of an inode; owning file in the case of a data block), insert a temporary \"dummy\" inode into the hash table so that inter-object links can be maintained until the absent inode is eventually restored. Dummy inodes are identified by a reference count of 0. If a delete record for an inode is encountered, the inode's parent pointer is set to null to indicate that it should be removed from RAM. If nffs encounters an object that cannot be identified (i.e., its magic number is not valid), it scans the remainder of the flash area for the next valid magic number. Upon encountering a valid object, nffs resumes the procedure described above. After all areas have been restored, a sweep is performed across the entire RAM representation so that invalid inodes can be deleted from memory. For each directory inode: If its reference count is 0 (i.e., it is a dummy), migrate its children to the /lost+found directory, and delete it from the RAM representation. This should only happen in the case of file system corruption. If its parent reference is null (i.e., it was deleted), delete it and all its children from the RAM representation. For each file inode: If its reference count is 0 (i.e., it is a dummy), delete it from the RAM representation. This should only happen in the case of file system corruption. (We should try to migrate the file to the lost+found directory in this case, as mentioned in the todo section). When an object is deleted during this sweep, it is only deleted from the RAM representation; nothing is written to disk. When objects are migrated to the lost+found directory, their parent inode reference is permanently updated on the disk. In addition, a single scratch area is identified during the detection process. The first area whose fda_id value is set to 0xff is designated as the file system scratch area. If no valid scratch area is found, the cause could be that the system was restarted while a garbage collection cycle was in progress. Such a condition is identified by the presence of two areas with the same ID. In such a case, the shorter of the two areas is erased and designated as the scratch area. Formatting A new nffs file system is created via formatting. Formatting is achieved via the nffs_format() function. During a successful format, an area header is written to each of the specified locations. One of the areas in the set is designated as the initial scratch area. Flash writes The nffs implementation always writes in a strictly sequential fashion within an area. For each area, the system keeps track of the current offset. Whenever an object gets written to an area, it gets written to that area's current offset, and the offset is increased by the object's disk size. When a write needs to be performed, the nffs implementation selects the appropriate destination area by iterating though each area until one with sufficient free space is encountered. There is no write buffering. Each call to a write function results in a write operation being sent to the flash hardware. New objects Whenever a new object is written to disk, it is assigned the following properties: ID: A unique value is selected from the 32-bit ID space, as appropriate for the object's type. Sequence number: 0 When a new file or directory is created, a corresponding inode is written to flash. Likewise, a new data block also results in the writing of a corresponding disk object. Moving/Renaming files and directories When a file or directory is moved or renamed, its corresponding inode is rewritten to flash with the following properties: ID: Unchanged Sequence number: Previous value plus one. Parent inode: As specified by the move / rename operation. Filename: As specified by the move / rename operation. Because the inode's ID is unchanged, all dependent objects remain valid. Unlinking files and directories When a file or directory is unlinked from its parent directory, a deletion record for the unlinked inode gets written to flash. The deletion record is an inode with the following properties: ID: Unchanged Sequence number: Previous value plus one. Parent inode ID: NFFS_ID_NONE When an inode is unlinked, no deletion records need to be written for the inode's dependent objects (constituent data blocks or child inodes). During the next file system detection, it is recognized that the objects belong to a deleted inode, so they are not restored into the RAM representation. If a file has an open handle at the time it gets unlinked, application code can continued to use the file handle to read and write data. All files retain a reference count, and a file isn't deleted from the RAM representation until its reference code drops to 0. Any attempt to open an unlinked file fails, even if the file is referenced by other file handles. Writing to a file The following procedure is used whenever the application code writes to a file. First, if the write operation specifies too much data to fit into a single block, the operation is split into several separate write operations. Then, for each write operation: Determine which existing blocks the write operation overlaps (n = number of overwritten blocks). If n = 0 , this is an append operation. Write a data block with the following properties: ID: New unique value. Sequence number: 0. Else (n > 1) , this write overlaps existing data. For each block in [1, 2, ... n-1] , write a new block containing the updated contents. Each new block supersedes the block it overwrites. That is, each block has the following properties: ID: Unchanged Sequence number: Previous value plus one. Write the nth block. The nth block includes all appended data, if any. As with the other blocks, its ID is unchanged and its sequence number is incremented. Appended data can only be written to the end of the file. That is, \"holes\" are not supported. Garbage collection When the file system is too full to accommodate a write operation, the system must perform garbage collection to make room. The garbage collection procedure is described below: The non-scratch area with the lowest garbage collection sequence number is selected as the \"source area.\" If there are other areas with the same sequence number, the one with the smallest flash offset is selected. The source area's ID is written to the scratch area's header, transforming it into a non-scratch ID. This former scratch area is now known as the \"destination area.\" The RAM representation is exhaustively searched for collectible objects. The following procedure is applied to each inode in the system: If the inode is resident in the source area, copy the inode record to the destination area. If the inode is a file inode, walk the inode's list of data blocks, starting with the last block in the file. Each block that is resident in the source area is copied to the destination area. If there is a run of two or more blocks that are resident in the source area, they are consolidated and copied to the destination area as a single new block (subject to the maximum block size restriction). The source area is reformatted as a scratch sector (i.e., is is fully erased, and its header is rewritten with an ID of 0xff). The area's garbage collection sequence number is incremented prior to rewriting the header. This area is now the new scratch sector.","title":"Internals"},{"location":"os/modules/fs/nffs/nffs_internals/#internals-of-nffs","text":"","title":"Internals of nffs"},{"location":"os/modules/fs/nffs/nffs_internals/#disk-structure","text":"On disk, each area is prefixed with the following header: /** On-disk representation of an area header. */ struct nffs_disk_area { uint32_t nda_magic [ 4 ]; /* NFFS_AREA_MAGIC{0,1,2,3} */ uint32_t nda_length ; /* Total size of area, in bytes. */ uint8_t nda_ver ; /* Current nffs version: 0 */ uint8_t nda_gc_seq ; /* Garbage collection count. */ uint8_t reserved8 ; uint8_t nda_id ; /* 0xff if scratch area. */ }; Beyond its header, an area contains a sequence of disk objects, representing the contents of the file system. There are two types of objects: inodes and data blocks . An inode represents a file or directory; a data block represents part of a file's contents. /** On-disk representation of an inode (file or directory). */ struct nffs_disk_inode { uint32_t ndi_magic ; /* NFFS_INODE_MAGIC */ uint32_t ndi_id ; /* Unique object ID. */ uint32_t ndi_seq ; /* Sequence number; greater supersedes lesser. */ uint32_t ndi_parent_id ; /* Object ID of parent directory inode. */ uint8_t reserved8 ; uint8_t ndi_filename_len ; /* Length of filename, in bytes. */ uint16_t ndi_crc16 ; /* Covers rest of header and filename. */ /* Followed by filename. */ }; An inode filename's length cannot exceed 256 bytes. The filename is not null-terminated. The following ASCII characters are not allowed in a filename: / (slash character) \\0 (NUL character) /** On-disk representation of a data block. */ struct nffs_disk_block { uint32_t ndb_magic ; /* NFFS_BLOCK_MAGIC */ uint32_t ndb_id ; /* Unique object ID. */ uint32_t ndb_seq ; /* Sequence number; greater supersedes lesser. */ uint32_t ndb_inode_id ; /* Object ID of owning inode. */ uint32_t ndb_prev_id ; /* Object ID of previous block in file; NFFS_ID_NONE if this is the first block. */ uint16_t ndb_data_len ; /* Length of data contents, in bytes. */ uint16_t ndb_crc16 ; /* Covers rest of header and data. */ /* Followed by 'ndb_data_len' bytes of data. */ }; Each data block contains the ID of the previous data block in the file. Together, the set of blocks in a file form a reverse singly-linked list. The maximum number of data bytes that a block can contain is determined at initialization-time. The result is the greatest number which satisfies all of the following restrictions: No more than 2048. At least two maximum-sized blocks can fit in the smallest area. The 2048 number was chosen somewhat arbitrarily, and may change in the future.","title":"Disk structure"},{"location":"os/modules/fs/nffs/nffs_internals/#id-space","text":"All disk objects have a unique 32-bit ID. The ID space is partitioned as follows: ID range Node type 0x00000000 - 0x0fffffff Directory inodes 0x10000000 - 0x7fffffff File inodes 0x80000000 - 0xfffffffe Data blocks 0xffffffff Reserved (NFFS_ID_NONE)","title":"ID space"},{"location":"os/modules/fs/nffs/nffs_internals/#scratch-area","text":"A valid nffs file system must contain a single \"scratch area.\" The scratch area does not contain any objects of its own, and is only used during garbage collection. The scratch area must have a size greater than or equal to each of the other areas in flash.","title":"Scratch area"},{"location":"os/modules/fs/nffs/nffs_internals/#ram-representation","text":"Every object in the file system is stored in a 256-entry hash table. An object's hash key is derived from its 32-bit ID. Each list in the hash table is sorted by time of use; most-recently-used is at the front of the list. All objects are represented by the following structure: /** * What gets stored in the hash table. Each entry represents a data block or * an inode. */ struct nffs_hash_entry { SLIST_ENTRY ( nffs_hash_entry ) nhe_next ; uint32_t nhe_id ; /* 0 - 0x7fffffff if inode; else if block. */ uint32_t nhe_flash_loc ; /* Upper-byte = area idx; rest = area offset. */ }; For each data block, the above structure is all that is stored in RAM. To acquire more information about a data block, the block header must be read from flash. Inodes require a fuller RAM representation to capture the structure of the file system. There are two types of inodes: files and directories . Each inode hash entry is actually an instance of the following structure: /** Each inode hash entry is actually one of these. */ struct nffs_inode_entry { struct nffs_hash_entry nie_hash_entry ; SLIST_ENTRY ( nffs_inode_entry ) nie_sibling_next ; union { struct nffs_inode_list nie_child_list ; /* If directory */ struct nffs_hash_entry *nie_last_block_entry ; /* If file */ }; uint8_t nie_refcnt ; }; A directory inode contains a list of its child files and directories ( fie_child_list ). These entries are sorted alphabetically using the ASCII character set. A file inode contains a pointer to the last data block in the file ( nie_last_block_entry ). For most file operations, the reversed block list must be walked backwards. This introduces a number of speed inefficiencies: All data blocks must be read to determine the length of the file. Data blocks often need to be processed sequentially. The reversed nature of the block list transforms this from linear time to an O(n^2) operation. Furthermore, obtaining information about any constituent data block requires a separate flash read.","title":"RAM representation"},{"location":"os/modules/fs/nffs/nffs_internals/#inode-cache-and-data-block-cache","text":"The speed issues are addressed by a pair of caches. Cached inodes entries contain the file length and a much more convenient doubly-linked list of cached data blocks. The benefit of using caches is that the size of the caches need not be proportional to the size of the file system. In other words, caches can address speed efficiency concerns without negatively impacting the file system's scalability. nffs requires both caches during normal operation, so it is not possible to disable them. However, the cache sizes are configurable, and both caches can be configured with a size of one if RAM usage must be minimized. The following data structures are used in the inode and data block caches. /** Full data block representation; not stored permanently in RAM. */ struct nffs_block { struct nffs_hash_entry *nb_hash_entry ; /* Points to real block entry. */ uint32_t nb_seq ; /* Sequence number; greater supersedes lesser. */ struct nffs_inode_entry *nb_inode_entry ; /* Owning inode. */ struct nffs_hash_entry *nb_prev ; /* Previous block in file. */ uint16_t nb_data_len ; /* # of data bytes in block. */ uint16_t reserved16 ; }; /** Represents a single cached data block. */ struct nffs_cache_block { TAILQ_ENTRY ( nffs_cache_block ) ncb_link ; /* Next / prev cached block. */ struct nffs_block ncb_block ; /* Full data block. */ uint32_t ncb_file_offset ; /* File offset of this block. */ }; /** Full inode representation; not stored permanently in RAM. */ struct nffs_inode { struct nffs_inode_entry *ni_inode_entry ; /* Points to real inode entry. */ uint32_t ni_seq ; /* Sequence number; greater supersedes lesser. */ struct nffs_inode_entry *ni_parent ; /* Points to parent directory. */ uint8_t ni_filename_len ; /* # chars in filename. */ uint8_t ni_filename [ NFFS_SHORT_FILENAME_LEN ]; /* First 3 bytes. */ }; /** Doubly-linked tail queue of cached blocks; contained in cached inodes. */ TAILQ_HEAD ( nffs_block_cache_list , nffs_block_cache_entry ); /** Represents a single cached file inode. */ struct nffs_cache_inode { TAILQ_ENTRY ( nffs_cache_inode ) nci_link ; /* Sorted; LRU at tail. */ struct nffs_inode nci_inode ; /* Full inode. */ struct nffs_cache_block_list nci_block_list ; /* List of cached blocks. */ uint32_t nci_file_size ; /* Total file size. */ }; Only file inodes are cached; directory inodes are never cached. Within a cached inode, all cached data blocks are contiguous. E.g., if the start and end of a file are cached, then the middle must also be cached. A data block is only cached if its owning file is also cached. Internally, cached inodes are stored in a singly-linked list, ordered by time of use. The most-recently-used entry is the first element in the list. If a new inode needs to be cached, but the inode cache is full, the least-recently-used entry is freed to make room for the new one. The following operations cause an inode to be cached: Querying a file's length. Seeking within a file. Reading from a file. Writing to a file. The following operations cause a data block to be cached: Reading from the block. Writing to the block. If one of the above operations is applied to a data block that is not currently cached, nffs uses the following procedure to cache the necessary block: If none of the owning inode's blocks are currently cached, allocate a cached block entry corresponding to the requested block and insert it into the inode's list. Else if the requested file offset is less than that of the first cached block, bridge the gap between the inode's sequence of cached blocks and the block that now needs to be cached. This is accomplished by caching each block in the gap, finishing with the requested block. Else (the requested offset is beyond the end of the cache), If the requested offset belongs to the block that immediately follows the end of the cache, cache the block and append it to the list. Else, clear the cache, and populate it with the single entry corresponding to the requested block. If the system is unable to allocate a cached block entry at any point during the above procedure, the system frees up other blocks currently in the cache. This is accomplished as follows: Iterate the inode cache in reverse (i.e., start with the least-recently-used entry). For each entry: If the entry's cached block list is empty, advance to the next entry. Else, free all the cached blocks in the entry's list. Because the system imposes a minimum block cache size of one, the above procedure will always reclaim at least one cache block entry. The above procedure may result in the freeing of the block list that belongs to the very inode being operated on. This is OK, as the final block to get cached is always the block being requested.","title":"Inode cache and Data Block cache"},{"location":"os/modules/fs/nffs/nffs_internals/#detection","text":"The file system detection process consists of scanning a specified set of flash regions for valid nffs areas, and then populating the RAM representation of the file system with the detected objects. Detection is initiated with the nffs_detect() function. Not every area descriptor passed to nffs_detect() needs to reference a valid nffs area. Detection is successful as long as a complete file system is detected somewhere in the specified regions of flash. If an application is unsure where a file system might be located, it can initiate detection across the entire flash region. A detected file system is valid if: At least one non-scratch area is present. At least one scratch area is present (only the first gets used if there is more than one). The root directory inode is present. During detection, each indicated region of flash is checked for a valid area header. The contents of each valid non-scratch area are then restored into the nffs RAM representation. The following procedure is applied to each object in the area: Verify the object's integrity via a crc16 check. If invalid, the object is discarded and the procedure restarts on the next object in the area. Convert the disk object into its corresponding RAM representation and insert it into the hash table. If the object is an inode, its reference count is initialized to 1, indicating ownership by its parent directory. If an object with the same ID is already present, then one supersedes the other. Accept the object with the greater sequence number and discard the other. If the object references a nonexistent inode (parent directory in the case of an inode; owning file in the case of a data block), insert a temporary \"dummy\" inode into the hash table so that inter-object links can be maintained until the absent inode is eventually restored. Dummy inodes are identified by a reference count of 0. If a delete record for an inode is encountered, the inode's parent pointer is set to null to indicate that it should be removed from RAM. If nffs encounters an object that cannot be identified (i.e., its magic number is not valid), it scans the remainder of the flash area for the next valid magic number. Upon encountering a valid object, nffs resumes the procedure described above. After all areas have been restored, a sweep is performed across the entire RAM representation so that invalid inodes can be deleted from memory. For each directory inode: If its reference count is 0 (i.e., it is a dummy), migrate its children to the /lost+found directory, and delete it from the RAM representation. This should only happen in the case of file system corruption. If its parent reference is null (i.e., it was deleted), delete it and all its children from the RAM representation. For each file inode: If its reference count is 0 (i.e., it is a dummy), delete it from the RAM representation. This should only happen in the case of file system corruption. (We should try to migrate the file to the lost+found directory in this case, as mentioned in the todo section). When an object is deleted during this sweep, it is only deleted from the RAM representation; nothing is written to disk. When objects are migrated to the lost+found directory, their parent inode reference is permanently updated on the disk. In addition, a single scratch area is identified during the detection process. The first area whose fda_id value is set to 0xff is designated as the file system scratch area. If no valid scratch area is found, the cause could be that the system was restarted while a garbage collection cycle was in progress. Such a condition is identified by the presence of two areas with the same ID. In such a case, the shorter of the two areas is erased and designated as the scratch area.","title":"Detection"},{"location":"os/modules/fs/nffs/nffs_internals/#formatting","text":"A new nffs file system is created via formatting. Formatting is achieved via the nffs_format() function. During a successful format, an area header is written to each of the specified locations. One of the areas in the set is designated as the initial scratch area.","title":"Formatting"},{"location":"os/modules/fs/nffs/nffs_internals/#flash-writes","text":"The nffs implementation always writes in a strictly sequential fashion within an area. For each area, the system keeps track of the current offset. Whenever an object gets written to an area, it gets written to that area's current offset, and the offset is increased by the object's disk size. When a write needs to be performed, the nffs implementation selects the appropriate destination area by iterating though each area until one with sufficient free space is encountered. There is no write buffering. Each call to a write function results in a write operation being sent to the flash hardware.","title":"Flash writes"},{"location":"os/modules/fs/nffs/nffs_internals/#new-objects","text":"Whenever a new object is written to disk, it is assigned the following properties: ID: A unique value is selected from the 32-bit ID space, as appropriate for the object's type. Sequence number: 0 When a new file or directory is created, a corresponding inode is written to flash. Likewise, a new data block also results in the writing of a corresponding disk object.","title":"New objects"},{"location":"os/modules/fs/nffs/nffs_internals/#movingrenaming-files-and-directories","text":"When a file or directory is moved or renamed, its corresponding inode is rewritten to flash with the following properties: ID: Unchanged Sequence number: Previous value plus one. Parent inode: As specified by the move / rename operation. Filename: As specified by the move / rename operation. Because the inode's ID is unchanged, all dependent objects remain valid.","title":"Moving/Renaming files and directories"},{"location":"os/modules/fs/nffs/nffs_internals/#unlinking-files-and-directories","text":"When a file or directory is unlinked from its parent directory, a deletion record for the unlinked inode gets written to flash. The deletion record is an inode with the following properties: ID: Unchanged Sequence number: Previous value plus one. Parent inode ID: NFFS_ID_NONE When an inode is unlinked, no deletion records need to be written for the inode's dependent objects (constituent data blocks or child inodes). During the next file system detection, it is recognized that the objects belong to a deleted inode, so they are not restored into the RAM representation. If a file has an open handle at the time it gets unlinked, application code can continued to use the file handle to read and write data. All files retain a reference count, and a file isn't deleted from the RAM representation until its reference code drops to 0. Any attempt to open an unlinked file fails, even if the file is referenced by other file handles.","title":"Unlinking files and directories"},{"location":"os/modules/fs/nffs/nffs_internals/#writing-to-a-file","text":"The following procedure is used whenever the application code writes to a file. First, if the write operation specifies too much data to fit into a single block, the operation is split into several separate write operations. Then, for each write operation: Determine which existing blocks the write operation overlaps (n = number of overwritten blocks). If n = 0 , this is an append operation. Write a data block with the following properties: ID: New unique value. Sequence number: 0. Else (n > 1) , this write overlaps existing data. For each block in [1, 2, ... n-1] , write a new block containing the updated contents. Each new block supersedes the block it overwrites. That is, each block has the following properties: ID: Unchanged Sequence number: Previous value plus one. Write the nth block. The nth block includes all appended data, if any. As with the other blocks, its ID is unchanged and its sequence number is incremented. Appended data can only be written to the end of the file. That is, \"holes\" are not supported.","title":"Writing to a file"},{"location":"os/modules/fs/nffs/nffs_internals/#garbage-collection","text":"When the file system is too full to accommodate a write operation, the system must perform garbage collection to make room. The garbage collection procedure is described below: The non-scratch area with the lowest garbage collection sequence number is selected as the \"source area.\" If there are other areas with the same sequence number, the one with the smallest flash offset is selected. The source area's ID is written to the scratch area's header, transforming it into a non-scratch ID. This former scratch area is now known as the \"destination area.\" The RAM representation is exhaustively searched for collectible objects. The following procedure is applied to each inode in the system: If the inode is resident in the source area, copy the inode record to the destination area. If the inode is a file inode, walk the inode's list of data blocks, starting with the last block in the file. Each block that is resident in the source area is copied to the destination area. If there is a run of two or more blocks that are resident in the source area, they are consolidated and copied to the destination area as a single new block (subject to the maximum block size restriction). The source area is reformatted as a scratch sector (i.e., is is fully erased, and its header is rewritten with an ID of 0xff). The area's garbage collection sequence number is incremented prior to rewriting the header. This area is now the new scratch sector.","title":"Garbage collection"},{"location":"os/modules/hal/hal/","text":"Hardware Abstraction Layer Description The Hardware Abstraction Layer (HAL) in Mynewt is a low-level, base peripheral abstraction. HAL provides a core set of services that is implemented for each MCU supported by Mynewt. Device drivers are typically the software libraries that initialize the hardware and manage access to the hardware by higher layers of software. In the Mynewt OS, the layers can be depicted in the following manner. +\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014+ | app | +\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014+ | (n)drivers | +\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014+ | HAL | BSP | +\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014+\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014+ The Board Support Package (BSP) abstracts board specific configurations e.g. CPU frequency, input voltage, LED pins, on-chip flash map etc. The Hardware Abstraction Layer (HAL) abstracts architecture-specific functionality. It initializes and enables components within a master processor. It is designed to be portable across all the various MCUs supported in Mynewt (e.g. Nordic's nRF51, Nordic's nRF52, NXP's MK64F12 etc.). It includes code that initializes and manages access to components of the board such as board buses (I2C, PCI, PCMCIA, etc.), off-chip memory (controllers, level 2+ cache, Flash, etc.), and off-chip I/O (Ethernet, RS-232, display, mouse, etc.) The driver sits atop the BSP and HAL. It abstracts the common modes of operation for each peripheral device connected via the standard interfaces to the processor. There may be multiple driver implementations of differing complexities for a particular peripheral device. The drivers are the ones that register with the kernel\u2019s power management APIs, and manage turning on and off peripherals and external chipsets, etc. General design principles The HAL API should be simple. It should be as easy to implement for hardware as possible. A simple HAL API makes it easy to bring up new MCUs quickly. The HAL API should portable across all the various MCUs supported in Mynewt (e.g. Nordic's nRF51, Nordic's nRF52, NXP's MK64F12 etc.). Example A Mynewt contributor might write a light-switch driver that provides the functionality of an intelligent light switch. This might involve using a timer, a General Purpose Output (GPO) to set the light to the on or off state, and flash memory to log the times the lights were turned on or off. The contributor would like this package to work with as many different hardware platforms as possible, but can't possibly test across the complete set of hardware supported by Mynewt. Solution : The contributor uses the HAL APIs to control the peripherals. The Mynewt team ensures that the underlying HAL devices all work equivalently through the HAL APIs. The contributors library is independent of the specifics of the hardware. Dependency To include the HAL within your project, simply add it to your package dependencies as follows: pkg.deps: . . . hw/hal Platform Support Not all platforms (MCU and BSP) support all HAL devices. Consult your MCU or BSP documentation to find out if you have hardware support for the peripherals you are interested in using. Once you verify support, then consult the MCU implementation and see if the specific HAL interface (xxxx) you are using is in the mcu/<mcu-name>/src/hal_xxxx.c implementation. Finally, you can build your project and ensure that there are no unresolved hal_xxxx externals.","title":"toc"},{"location":"os/modules/hal/hal/#hardware-abstraction-layer","text":"","title":"Hardware Abstraction Layer"},{"location":"os/modules/hal/hal/#description","text":"The Hardware Abstraction Layer (HAL) in Mynewt is a low-level, base peripheral abstraction. HAL provides a core set of services that is implemented for each MCU supported by Mynewt. Device drivers are typically the software libraries that initialize the hardware and manage access to the hardware by higher layers of software. In the Mynewt OS, the layers can be depicted in the following manner. +\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014+ | app | +\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014+ | (n)drivers | +\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014+ | HAL | BSP | +\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014+\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014+ The Board Support Package (BSP) abstracts board specific configurations e.g. CPU frequency, input voltage, LED pins, on-chip flash map etc. The Hardware Abstraction Layer (HAL) abstracts architecture-specific functionality. It initializes and enables components within a master processor. It is designed to be portable across all the various MCUs supported in Mynewt (e.g. Nordic's nRF51, Nordic's nRF52, NXP's MK64F12 etc.). It includes code that initializes and manages access to components of the board such as board buses (I2C, PCI, PCMCIA, etc.), off-chip memory (controllers, level 2+ cache, Flash, etc.), and off-chip I/O (Ethernet, RS-232, display, mouse, etc.) The driver sits atop the BSP and HAL. It abstracts the common modes of operation for each peripheral device connected via the standard interfaces to the processor. There may be multiple driver implementations of differing complexities for a particular peripheral device. The drivers are the ones that register with the kernel\u2019s power management APIs, and manage turning on and off peripherals and external chipsets, etc.","title":"Description"},{"location":"os/modules/hal/hal/#general-design-principles","text":"The HAL API should be simple. It should be as easy to implement for hardware as possible. A simple HAL API makes it easy to bring up new MCUs quickly. The HAL API should portable across all the various MCUs supported in Mynewt (e.g. Nordic's nRF51, Nordic's nRF52, NXP's MK64F12 etc.).","title":"General design principles"},{"location":"os/modules/hal/hal/#example","text":"A Mynewt contributor might write a light-switch driver that provides the functionality of an intelligent light switch. This might involve using a timer, a General Purpose Output (GPO) to set the light to the on or off state, and flash memory to log the times the lights were turned on or off. The contributor would like this package to work with as many different hardware platforms as possible, but can't possibly test across the complete set of hardware supported by Mynewt. Solution : The contributor uses the HAL APIs to control the peripherals. The Mynewt team ensures that the underlying HAL devices all work equivalently through the HAL APIs. The contributors library is independent of the specifics of the hardware.","title":"Example"},{"location":"os/modules/hal/hal/#dependency","text":"To include the HAL within your project, simply add it to your package dependencies as follows: pkg.deps: . . . hw/hal","title":"Dependency"},{"location":"os/modules/hal/hal/#platform-support","text":"Not all platforms (MCU and BSP) support all HAL devices. Consult your MCU or BSP documentation to find out if you have hardware support for the peripherals you are interested in using. Once you verify support, then consult the MCU implementation and see if the specific HAL interface (xxxx) you are using is in the mcu/<mcu-name>/src/hal_xxxx.c implementation. Finally, you can build your project and ensure that there are no unresolved hal_xxxx externals.","title":"Platform Support"},{"location":"os/modules/hal/hal_api/","text":"HAL Interfaces The HAL supports separate interfaces for many peripherals. A brief description of the interfaces are shown below. Hal Name ** Interface File ** **Description ** bsp hal_bsp.h An hardware independent interface to identify and access underlying BSP. flash api for apps to use hal_flash.h A blocking interface to access flash memory. flash api for drivers to implement flash_map.h An interface to query information about the flash map (regions and sectors) gpio hal_gpio.h An interface for manipulating General Purpose Inputs and Outputs. i2c hal_i2c.h An interface for controlling Inter-Integrated-Circuit (i2c) devices. OS tick hal_os_tick.h An interface to set up interrupt timers or halt CPU in terms of OS ticks. spi hal_spi.h An interface for controlling Serial Peripheral Interface (SPI) devices. system hal_system.h An interface for starting and resetting the system. timer hal_cputime.h An interface for configuring and running HW timers uart hal_uart.h An interface for communicating via asynchronous serial interface. watchdog hal_watchdog.h An interface for enabling internal hardware watchdogs.","title":"Summary"},{"location":"os/modules/hal/hal_api/#hal-interfaces","text":"The HAL supports separate interfaces for many peripherals. A brief description of the interfaces are shown below. Hal Name ** Interface File ** **Description ** bsp hal_bsp.h An hardware independent interface to identify and access underlying BSP. flash api for apps to use hal_flash.h A blocking interface to access flash memory. flash api for drivers to implement flash_map.h An interface to query information about the flash map (regions and sectors) gpio hal_gpio.h An interface for manipulating General Purpose Inputs and Outputs. i2c hal_i2c.h An interface for controlling Inter-Integrated-Circuit (i2c) devices. OS tick hal_os_tick.h An interface to set up interrupt timers or halt CPU in terms of OS ticks. spi hal_spi.h An interface for controlling Serial Peripheral Interface (SPI) devices. system hal_system.h An interface for starting and resetting the system. timer hal_cputime.h An interface for configuring and running HW timers uart hal_uart.h An interface for communicating via asynchronous serial interface. watchdog hal_watchdog.h An interface for enabling internal hardware watchdogs.","title":"HAL Interfaces"},{"location":"os/modules/hal/hal_creation/","text":"Creating New HAL Interfaces HAL API A HAL always includes header file with function declarations for the HAL functionality in /hw/hal/include/hal . The first argument of all functions in the interface typically include the virtual device_id of the device you are controlling. For example, in hal_gpio.h the device enumeration is the first argument to most methods and called pin . void hal_gpio_write(int pin, int val); The device_id (in this case called pin ) is not a physical device (actual hardware pin), but a virtual pin which is defined by the implementation of the HAL (and documented in the implementation of the HAL).","title":"Creating HAL"},{"location":"os/modules/hal/hal_creation/#creating-new-hal-interfaces","text":"","title":"Creating New HAL Interfaces"},{"location":"os/modules/hal/hal_creation/#hal-api","text":"A HAL always includes header file with function declarations for the HAL functionality in /hw/hal/include/hal . The first argument of all functions in the interface typically include the virtual device_id of the device you are controlling. For example, in hal_gpio.h the device enumeration is the first argument to most methods and called pin . void hal_gpio_write(int pin, int val); The device_id (in this case called pin ) is not a physical device (actual hardware pin), but a virtual pin which is defined by the implementation of the HAL (and documented in the implementation of the HAL).","title":"HAL API"},{"location":"os/modules/hal/hal_in_libraries/","text":"Using HAL in Your Libraries This page describes the recommended way to implement libraries that utilize HAL functionality. An example of the GPIO HAL being used by a driver for a UART bitbanger that programs the start bit, data bits, and stop bit can be seen in hw/drivers/uart/uart_bitbang/src/uart_bitbang.c An example of the flash HAL being used by a file sytem can be seen in fs/nffs/src/nffs_flash.c .","title":"Using HAL"},{"location":"os/modules/hal/hal_in_libraries/#using-hal-in-your-libraries","text":"This page describes the recommended way to implement libraries that utilize HAL functionality. An example of the GPIO HAL being used by a driver for a UART bitbanger that programs the start bit, data bits, and stop bit can be seen in hw/drivers/uart/uart_bitbang/src/uart_bitbang.c An example of the flash HAL being used by a file sytem can be seen in fs/nffs/src/nffs_flash.c .","title":"Using HAL in Your Libraries"},{"location":"os/modules/hal/hal_bsp/hal_bsp/","text":"hal_bsp This is the hardware independent BSP (Board Support Package) Interface for Mynewt. Description Contains the basic operations to initialize, specify memory to include in coredump, configure interrupt priority etc. Definition hal_bsp.h Examples","title":"BSP"},{"location":"os/modules/hal/hal_bsp/hal_bsp/#hal_bsp","text":"This is the hardware independent BSP (Board Support Package) Interface for Mynewt.","title":"hal_bsp"},{"location":"os/modules/hal/hal_bsp/hal_bsp/#description","text":"Contains the basic operations to initialize, specify memory to include in coredump, configure interrupt priority etc.","title":"Description"},{"location":"os/modules/hal/hal_bsp/hal_bsp/#definition","text":"hal_bsp.h","title":"Definition"},{"location":"os/modules/hal/hal_bsp/hal_bsp/#examples","text":"","title":"Examples"},{"location":"os/modules/hal/hal_flash/hal_flash/","text":"hal_flash The hardware independent interface to flash memory that is used by applications. Description The API offers basic initialization, read, write, erase, sector erase, and other operations. Definition hal_flash.h Examples","title":"flash API for apps"},{"location":"os/modules/hal/hal_flash/hal_flash/#hal_flash","text":"The hardware independent interface to flash memory that is used by applications.","title":"hal_flash"},{"location":"os/modules/hal/hal_flash/hal_flash/#description","text":"The API offers basic initialization, read, write, erase, sector erase, and other operations.","title":"Description"},{"location":"os/modules/hal/hal_flash/hal_flash/#definition","text":"hal_flash.h","title":"Definition"},{"location":"os/modules/hal/hal_flash/hal_flash/#examples","text":"","title":"Examples"},{"location":"os/modules/hal/hal_flash/hal_flash_int/","text":"hal_flash_int The API that flash drivers have to implement. Description The BSP for the hardware will implement the structs defined in this API. Definition hal_flash_int.h Examples The Nordic nRF52 bsp implements the hal_flash_int API as seen in hal_bsp.c const struct hal_flash * hal_bsp_flash_dev(uint8_t id) { /* * Internal flash mapped to id 0. */ if (id != 0) { return NULL; } return &nrf52k_flash_dev; }","title":"flash_int"},{"location":"os/modules/hal/hal_flash/hal_flash_int/#hal_flash_int","text":"The API that flash drivers have to implement.","title":"hal_flash_int"},{"location":"os/modules/hal/hal_flash/hal_flash_int/#description","text":"The BSP for the hardware will implement the structs defined in this API.","title":"Description"},{"location":"os/modules/hal/hal_flash/hal_flash_int/#definition","text":"hal_flash_int.h","title":"Definition"},{"location":"os/modules/hal/hal_flash/hal_flash_int/#examples","text":"The Nordic nRF52 bsp implements the hal_flash_int API as seen in hal_bsp.c const struct hal_flash * hal_bsp_flash_dev(uint8_t id) { /* * Internal flash mapped to id 0. */ if (id != 0) { return NULL; } return &nrf52k_flash_dev; }","title":"Examples"},{"location":"os/modules/hal/hal_gpio/hal_gpio/","text":"hal_gpio This is the hardware independent GPIO (General Purpose Input Output) Interface for Mynewt. Description Contains the basic operations to set and read General Purpose Digital I/O Pins within a Mynewt system. Individual GPIOs are referenced in the APIs as pins . However, in this interface the pins are virtual GPIO pins. The MCU header file maps these virtual pins to the physical GPIO ports and pins. Typically, the BSP code may define named I/O pins in terms of these virtual pins to describe the devices attached to the physical pins. Here's a brief example so you can get the gist of the translation. Suppose my product uses the stm32F4xx processor. There already exists support for this processor within Mynewt. The processor has N ports (A,B,C..) of 16 GPIO pins per port. The MCU hal_gpio driver maps these to a set of virtual pins 0-N where port A maps to 0-15, Port B maps to 16-31, Port C maps to 32-47 and so on. The exact number of physical port (and virtual port pins) depends on the specific variant of the stm32F4xx. So if I want to turn on port B pin 3, that would be virtual pin 1*16 + 3 = 19. This translation is defined in the MCU implementation of hal_gpio.c for the stmf32F4xx. Each MCU will typically have a different translation method depending on its GPIO architecture. Now, when writing a BSP, it's common to give names to the relevant port pins that you are using. Thus, the BSP may define a mapping between a function and a virtual port pin in the bsp.h header file for the BSP. For example, #define SYSTEM_LED (37) #define FLASH_SPI_CHIP_SELECT (3) would map the system indicator LED to virtual pin 37 which on the stm32F4xx would be Port C pin 5 and the chip select line for the external SPI flash to virtual pin 3 which on the stm32F4xxis port A pin 3. Said another way, in this specific system we get SYSTEM_LED --> hal_gpio virtual pin 37 --> port C pin 5 on the stm34F4xx Definition hal_gpio.h Examples Blinky Blinky uses the hal_gpio to blink the system LED. The blinky source code is available in the blinky repo . Examine how blinky_task_handler initializes and toggles the GPIO to control the LED.","title":"GPIO"},{"location":"os/modules/hal/hal_gpio/hal_gpio/#hal_gpio","text":"This is the hardware independent GPIO (General Purpose Input Output) Interface for Mynewt.","title":"hal_gpio"},{"location":"os/modules/hal/hal_gpio/hal_gpio/#description","text":"Contains the basic operations to set and read General Purpose Digital I/O Pins within a Mynewt system. Individual GPIOs are referenced in the APIs as pins . However, in this interface the pins are virtual GPIO pins. The MCU header file maps these virtual pins to the physical GPIO ports and pins. Typically, the BSP code may define named I/O pins in terms of these virtual pins to describe the devices attached to the physical pins. Here's a brief example so you can get the gist of the translation. Suppose my product uses the stm32F4xx processor. There already exists support for this processor within Mynewt. The processor has N ports (A,B,C..) of 16 GPIO pins per port. The MCU hal_gpio driver maps these to a set of virtual pins 0-N where port A maps to 0-15, Port B maps to 16-31, Port C maps to 32-47 and so on. The exact number of physical port (and virtual port pins) depends on the specific variant of the stm32F4xx. So if I want to turn on port B pin 3, that would be virtual pin 1*16 + 3 = 19. This translation is defined in the MCU implementation of hal_gpio.c for the stmf32F4xx. Each MCU will typically have a different translation method depending on its GPIO architecture. Now, when writing a BSP, it's common to give names to the relevant port pins that you are using. Thus, the BSP may define a mapping between a function and a virtual port pin in the bsp.h header file for the BSP. For example, #define SYSTEM_LED (37) #define FLASH_SPI_CHIP_SELECT (3) would map the system indicator LED to virtual pin 37 which on the stm32F4xx would be Port C pin 5 and the chip select line for the external SPI flash to virtual pin 3 which on the stm32F4xxis port A pin 3. Said another way, in this specific system we get SYSTEM_LED --> hal_gpio virtual pin 37 --> port C pin 5 on the stm34F4xx","title":"Description"},{"location":"os/modules/hal/hal_gpio/hal_gpio/#definition","text":"hal_gpio.h","title":"Definition"},{"location":"os/modules/hal/hal_gpio/hal_gpio/#examples","text":"","title":"Examples"},{"location":"os/modules/hal/hal_gpio/hal_gpio/#blinky","text":"Blinky uses the hal_gpio to blink the system LED. The blinky source code is available in the blinky repo . Examine how blinky_task_handler initializes and toggles the GPIO to control the LED.","title":"Blinky"},{"location":"os/modules/hal/hal_i2c/hal_i2c/","text":"hal_i2c The hardware independent interface to I2C Devices. Description An Inter-Integrated Circuit (I\u00b2C ] I-squared-C) bus is a multi-master, multi-save serial interface used to connect components on a circuit board and often peripherals devices located off the circuit board. I2C is often though of as a 2-wire protocol because it uses two wires (SDA, SCL) to send data between devices. For a detailed description of I2C, see the I\u00b2C wikipedia page Definition hal_i2c.h HAL_I2C Theory Of Operation An I\u00b2C transaction typically involves acquiring the bus, sending and/or receiving data and release the bus. The bus acquisition portion is important because the bus is typically multi-master so other devices may be trying to read/write the same peripheral. HAL_I2C implements a master interface to the I\u00b2C bus. Typical usage of the interface would involve the following steps. Initialize an i2c device with: hal_i2c_init() When you wish to perform an i2c transaction, you call one or both of: hal_i2c_master_write(); hal_i2c_master_read(); These functions will issue a START condition, followed by the device's 7-bit I2C address, and then send or receive the payload based on the data provided. This will cause a repeated start on the bus, which is valid in I2C specification, and the decision to use repeated starts was made to simplify the I2C HAL. To set the STOP condition at an appropriate moment, you set the last_op field to a 1 in either function. For example, in an I2C memory access you might write a register address and then read data back via: hal_i2c_write(); -- write to a specific register on the device hal_i2c_read(); --- read back data, setting 'last_op' to '1' An addition API was added called hal_i2c_probe . This command combines hal_i2c_begin() , hal_i2c_read , and hal_i2c_end() to try to read 0-bytes from a specific bus address. its intended to provide an easy way to probe the bus for a specific device. NOTE: if the device is write-only, it will not appear with this command. A slave API is pending for further release. HAL_I2C Data Data to read/write is passed to the hal_i2c APIs via the struct hal_i2c_master_data { uint8_t address; /* destination address */ uint16_t len; /* number of bytes to transmit or receive */ uint8_t *buffer; /* data buffer for transmit or receive */ }; buffer is a pointer to the data to send. len is the number of bytes to send over the bus. address is a 7-bit bus address of the device. When I\u00b2C builds its address, it uses the 7-bit address plus a 1-bit R/W (read/write) indicator to identify the device and direction of the transaction. Thus when using this API, you should use a 7-bit address in the data structure and ensure that address is a value between 0-127. As an example, consider an I\u00b2C device address that looks like this: B7 B6 B5 B4 B3 B2 B1 B0 1 0 0 0 1 1 0 R/W MSB LSB In the HAL_I2C API you would communicate with this device with address 0b1000110 , which is hex 0x46 or decimal 70. The I\u00b2C drive would add the R/W bit and transmit it as hex 0x8C (binary 10001100) or 0x8D (binary 10001101) depending whether it was a read or write command.","title":"I2C"},{"location":"os/modules/hal/hal_i2c/hal_i2c/#hal_i2c","text":"The hardware independent interface to I2C Devices.","title":"hal_i2c"},{"location":"os/modules/hal/hal_i2c/hal_i2c/#description","text":"An Inter-Integrated Circuit (I\u00b2C ] I-squared-C) bus is a multi-master, multi-save serial interface used to connect components on a circuit board and often peripherals devices located off the circuit board. I2C is often though of as a 2-wire protocol because it uses two wires (SDA, SCL) to send data between devices. For a detailed description of I2C, see the I\u00b2C wikipedia page","title":"Description"},{"location":"os/modules/hal/hal_i2c/hal_i2c/#definition","text":"hal_i2c.h","title":"Definition"},{"location":"os/modules/hal/hal_i2c/hal_i2c/#hal_i2c-theory-of-operation","text":"An I\u00b2C transaction typically involves acquiring the bus, sending and/or receiving data and release the bus. The bus acquisition portion is important because the bus is typically multi-master so other devices may be trying to read/write the same peripheral. HAL_I2C implements a master interface to the I\u00b2C bus. Typical usage of the interface would involve the following steps. Initialize an i2c device with: hal_i2c_init() When you wish to perform an i2c transaction, you call one or both of: hal_i2c_master_write(); hal_i2c_master_read(); These functions will issue a START condition, followed by the device's 7-bit I2C address, and then send or receive the payload based on the data provided. This will cause a repeated start on the bus, which is valid in I2C specification, and the decision to use repeated starts was made to simplify the I2C HAL. To set the STOP condition at an appropriate moment, you set the last_op field to a 1 in either function. For example, in an I2C memory access you might write a register address and then read data back via: hal_i2c_write(); -- write to a specific register on the device hal_i2c_read(); --- read back data, setting 'last_op' to '1' An addition API was added called hal_i2c_probe . This command combines hal_i2c_begin() , hal_i2c_read , and hal_i2c_end() to try to read 0-bytes from a specific bus address. its intended to provide an easy way to probe the bus for a specific device. NOTE: if the device is write-only, it will not appear with this command. A slave API is pending for further release.","title":"HAL_I2C Theory Of Operation"},{"location":"os/modules/hal/hal_i2c/hal_i2c/#hal_i2c-data","text":"Data to read/write is passed to the hal_i2c APIs via the struct hal_i2c_master_data { uint8_t address; /* destination address */ uint16_t len; /* number of bytes to transmit or receive */ uint8_t *buffer; /* data buffer for transmit or receive */ }; buffer is a pointer to the data to send. len is the number of bytes to send over the bus. address is a 7-bit bus address of the device. When I\u00b2C builds its address, it uses the 7-bit address plus a 1-bit R/W (read/write) indicator to identify the device and direction of the transaction. Thus when using this API, you should use a 7-bit address in the data structure and ensure that address is a value between 0-127. As an example, consider an I\u00b2C device address that looks like this: B7 B6 B5 B4 B3 B2 B1 B0 1 0 0 0 1 1 0 R/W MSB LSB In the HAL_I2C API you would communicate with this device with address 0b1000110 , which is hex 0x46 or decimal 70. The I\u00b2C drive would add the R/W bit and transmit it as hex 0x8C (binary 10001100) or 0x8D (binary 10001101) depending whether it was a read or write command.","title":"HAL_I2C Data"},{"location":"os/modules/hal/hal_os_tick/hal_os_tick/","text":"hal_os_tick The hardware independent interface to set up interrupt timers or halt CPU in terms of OS ticks. Description Set up the periodic timer to interrupt at a frequency of 'os_ticks_per_sec' using the following function call where 'prio' is the cpu-specific priority of the periodic timer interrupt. void os_tick_init ( uint32_t os_ticks_per_sec , int prio ); You can halt CPU for up to n ticks: void os_tick_idle ( os_time_t n ); The function implementations are in the mcu-specific directories such as hw/mcu/nordic/nrf51xxx/src/hal_os_tick.c . Definition hal_os_tick.h Examples An example of the API being used by the OS kernel for the Cortex M0 architecture to initialize and start the system clock timer can be seen in kernel/os/src/arch/cortex_m0/os_arch_arm.c .","title":"OS Tick"},{"location":"os/modules/hal/hal_os_tick/hal_os_tick/#hal_os_tick","text":"The hardware independent interface to set up interrupt timers or halt CPU in terms of OS ticks.","title":"hal_os_tick"},{"location":"os/modules/hal/hal_os_tick/hal_os_tick/#description","text":"Set up the periodic timer to interrupt at a frequency of 'os_ticks_per_sec' using the following function call where 'prio' is the cpu-specific priority of the periodic timer interrupt. void os_tick_init ( uint32_t os_ticks_per_sec , int prio ); You can halt CPU for up to n ticks: void os_tick_idle ( os_time_t n ); The function implementations are in the mcu-specific directories such as hw/mcu/nordic/nrf51xxx/src/hal_os_tick.c .","title":"Description"},{"location":"os/modules/hal/hal_os_tick/hal_os_tick/#definition","text":"hal_os_tick.h","title":"Definition"},{"location":"os/modules/hal/hal_os_tick/hal_os_tick/#examples","text":"An example of the API being used by the OS kernel for the Cortex M0 architecture to initialize and start the system clock timer can be seen in kernel/os/src/arch/cortex_m0/os_arch_arm.c .","title":"Examples"},{"location":"os/modules/hal/hal_spi/hal_spi/","text":"hal_spi SPI (Serial Peripheral Interface) is a synchronous 4-wire serial interface commonly used to connect components in embedded systems. For a detailed description of SPI, see Wikipedia . Description The Mynewt HAL interface supports the SPI master functionality with both blocking and non-blocking interface. SPI slave functionality is supported in non-blocking mode. Definition hal_spi.h HAL_SPI Theory Of Operation SPI is called a 4-wire interface because of the 4 signals, MISO, MOSI, CLK, and SS. The SS signal (slave select) is an active low signal that activates a SPI slave device. This is how a master \"addresses\" a particular slave device. Often this signal is also referred to as \"chip select\" as it selects particular slave device for communications. The Mynewt SPI HAL has blocking and non-blocking transfers. Blocking means that the API call to transfer a byte will wait until the byte completes transmissions before the function returns. Blocking interface can be used for only the master slave SPI type. Non-blocking means he function returns control to the execution environment immediately after the API call and a callback function is executed at the completion of the transmission. Non-blocking interface can be used for both master and slave SPI types. The hal_spi_config method in the API above allows the SPI to be configured with appropriate settings for master or slave. It Must be called after the spi is initialized (i.e. after hal_spi_init is called) and when the spi is disabled (i.e. user must call hal_spi_disable if the spi has been enabled through hal_spi_enable prior to calling this function). It can also be used to reconfigure an initialized SPI (assuming it is disabled as described previously). int hal_spi_config ( int spi_num , struct hal_spi_settings *psettings ); The SPI settings consist of the following: struct hal_spi_settings { uint8_t data_mode ; uint8_t data_order ; uint8_t word_size ; uint32_t baudrate ; /* baudrate in kHz */ }; The Mynewt SPI HAL does not include built-in SS (Slave Select) signaling. It's up to the hal_spi user to control their own SS pins. Typically applications will do this with GPIO.","title":"SPI"},{"location":"os/modules/hal/hal_spi/hal_spi/#hal_spi","text":"SPI (Serial Peripheral Interface) is a synchronous 4-wire serial interface commonly used to connect components in embedded systems. For a detailed description of SPI, see Wikipedia .","title":"hal_spi"},{"location":"os/modules/hal/hal_spi/hal_spi/#description","text":"The Mynewt HAL interface supports the SPI master functionality with both blocking and non-blocking interface. SPI slave functionality is supported in non-blocking mode.","title":"Description"},{"location":"os/modules/hal/hal_spi/hal_spi/#definition","text":"hal_spi.h","title":"Definition"},{"location":"os/modules/hal/hal_spi/hal_spi/#hal_spi-theory-of-operation","text":"SPI is called a 4-wire interface because of the 4 signals, MISO, MOSI, CLK, and SS. The SS signal (slave select) is an active low signal that activates a SPI slave device. This is how a master \"addresses\" a particular slave device. Often this signal is also referred to as \"chip select\" as it selects particular slave device for communications. The Mynewt SPI HAL has blocking and non-blocking transfers. Blocking means that the API call to transfer a byte will wait until the byte completes transmissions before the function returns. Blocking interface can be used for only the master slave SPI type. Non-blocking means he function returns control to the execution environment immediately after the API call and a callback function is executed at the completion of the transmission. Non-blocking interface can be used for both master and slave SPI types. The hal_spi_config method in the API above allows the SPI to be configured with appropriate settings for master or slave. It Must be called after the spi is initialized (i.e. after hal_spi_init is called) and when the spi is disabled (i.e. user must call hal_spi_disable if the spi has been enabled through hal_spi_enable prior to calling this function). It can also be used to reconfigure an initialized SPI (assuming it is disabled as described previously). int hal_spi_config ( int spi_num , struct hal_spi_settings *psettings ); The SPI settings consist of the following: struct hal_spi_settings { uint8_t data_mode ; uint8_t data_order ; uint8_t word_size ; uint32_t baudrate ; /* baudrate in kHz */ }; The Mynewt SPI HAL does not include built-in SS (Slave Select) signaling. It's up to the hal_spi user to control their own SS pins. Typically applications will do this with GPIO.","title":"HAL_SPI Theory Of Operation"},{"location":"os/modules/hal/hal_system/hal_sys/","text":"hal_system A hardware independent interface for starting and resetting the system. Description The API allows the user to detect whether a debugger is connected, sissue a soft reset, and enumerate the reset causes. The functions are implemented in the MCU specific directories e.g. hal_reset_cause.c , hal_system.c , and hal_system_start.c in /hw/mcu/nordic/nrf52xxx/src/ directory for Nordic nRF52 series of chips. Definition hal_system.h Examples","title":"System"},{"location":"os/modules/hal/hal_system/hal_sys/#hal_system","text":"A hardware independent interface for starting and resetting the system.","title":"hal_system"},{"location":"os/modules/hal/hal_system/hal_sys/#description","text":"The API allows the user to detect whether a debugger is connected, sissue a soft reset, and enumerate the reset causes. The functions are implemented in the MCU specific directories e.g. hal_reset_cause.c , hal_system.c , and hal_system_start.c in /hw/mcu/nordic/nrf52xxx/src/ directory for Nordic nRF52 series of chips.","title":"Description"},{"location":"os/modules/hal/hal_system/hal_sys/#definition","text":"hal_system.h","title":"Definition"},{"location":"os/modules/hal/hal_system/hal_sys/#examples","text":"","title":"Examples"},{"location":"os/modules/hal/hal_timer/hal_timer/","text":"hal_timer The hardware independent timer structure and API to configure, initialize, and run timers. Description The HAL timer structure is shown below. The user can declare as many of these structures as required. They are enqueued on a particular HW timer queue when the user calls the hal_timer_start or hal_timer_start_at API. The user must have called hal_timer_set_cb before starting a timer. NOTE: the user should not have to modify/examine the contents of this structure; the hal timer API should be used. struct hal_timer { void *bsp_timer ; /* Internal platform specific pointer */ hal_timer_cb cb_func ; /* Callback function */ void *cb_arg ; /* Callback argument */ uint32_t expiry ; /* Tick at which timer should expire */ TAILQ_ENTRY ( hal_timer ) link ; /* Queue linked list structure */ }; Definition hal_timer.h Examples","title":"Timer"},{"location":"os/modules/hal/hal_timer/hal_timer/#hal_timer","text":"The hardware independent timer structure and API to configure, initialize, and run timers.","title":"hal_timer"},{"location":"os/modules/hal/hal_timer/hal_timer/#description","text":"The HAL timer structure is shown below. The user can declare as many of these structures as required. They are enqueued on a particular HW timer queue when the user calls the hal_timer_start or hal_timer_start_at API. The user must have called hal_timer_set_cb before starting a timer. NOTE: the user should not have to modify/examine the contents of this structure; the hal timer API should be used. struct hal_timer { void *bsp_timer ; /* Internal platform specific pointer */ hal_timer_cb cb_func ; /* Callback function */ void *cb_arg ; /* Callback argument */ uint32_t expiry ; /* Tick at which timer should expire */ TAILQ_ENTRY ( hal_timer ) link ; /* Queue linked list structure */ };","title":"Description"},{"location":"os/modules/hal/hal_timer/hal_timer/#definition","text":"hal_timer.h","title":"Definition"},{"location":"os/modules/hal/hal_timer/hal_timer/#examples","text":"","title":"Examples"},{"location":"os/modules/hal/hal_uart/hal_uart/","text":"hal_uart The hardware independent UART interface for Mynewt. Description Contains the basic operations to send and receive data over a UART (Universal Asynchronous Receiver Transmitter). It also includes the API to apply settings such as speed, parity etc. to the UART. The UART port should be closed before any reconfiguring. Definition hal_uart.h Examples This example shows a user writing a character to the uart in blocking mode where the UART has to block until character has been sent. /* write to the console with blocking */ { char *str = \"Hello World!\"; char *ptr = str; while(*ptr) { hal_uart_blocking_tx(MY_UART, *ptr++); } hal_uart_blocking_tx(MY_UART, '\\n'); }","title":"UART"},{"location":"os/modules/hal/hal_uart/hal_uart/#hal_uart","text":"The hardware independent UART interface for Mynewt.","title":"hal_uart"},{"location":"os/modules/hal/hal_uart/hal_uart/#description","text":"Contains the basic operations to send and receive data over a UART (Universal Asynchronous Receiver Transmitter). It also includes the API to apply settings such as speed, parity etc. to the UART. The UART port should be closed before any reconfiguring.","title":"Description"},{"location":"os/modules/hal/hal_uart/hal_uart/#definition","text":"hal_uart.h","title":"Definition"},{"location":"os/modules/hal/hal_uart/hal_uart/#examples","text":"This example shows a user writing a character to the uart in blocking mode where the UART has to block until character has been sent. /* write to the console with blocking */ { char *str = \"Hello World!\"; char *ptr = str; while(*ptr) { hal_uart_blocking_tx(MY_UART, *ptr++); } hal_uart_blocking_tx(MY_UART, '\\n'); }","title":"Examples"},{"location":"os/modules/hal/hal_watchdog/hal_watchdog/","text":"hal_watchdog The hardware independent interface to enable internal hardware watchdogs. Description The hal_watchdog_init interface can be used to set a recurring watchdog timer to fire no sooner than in 'expire_secs' seconds. int hal_watchdog_init ( uint32_t expire_msecs ); Watchdog needs to be then started with a call to hal_watchdog_enable() . Watchdog should be tickled periodically with a frequency smaller than 'expire_secs' using hal_watchdog_tickle() . Definition hal_watchdog Examples The OS initializes and starts a watchdog timer and tickles it periodically to check that the OS is running properly. This can be seen in /kernel/os/src/os.c .","title":"Watchdog"},{"location":"os/modules/hal/hal_watchdog/hal_watchdog/#hal_watchdog","text":"The hardware independent interface to enable internal hardware watchdogs.","title":"hal_watchdog"},{"location":"os/modules/hal/hal_watchdog/hal_watchdog/#description","text":"The hal_watchdog_init interface can be used to set a recurring watchdog timer to fire no sooner than in 'expire_secs' seconds. int hal_watchdog_init ( uint32_t expire_msecs ); Watchdog needs to be then started with a call to hal_watchdog_enable() . Watchdog should be tickled periodically with a frequency smaller than 'expire_secs' using hal_watchdog_tickle() .","title":"Description"},{"location":"os/modules/hal/hal_watchdog/hal_watchdog/#definition","text":"hal_watchdog","title":"Definition"},{"location":"os/modules/hal/hal_watchdog/hal_watchdog/#examples","text":"The OS initializes and starts a watchdog timer and tickles it periodically to check that the OS is running properly. This can be seen in /kernel/os/src/os.c .","title":"Examples"},{"location":"os/modules/imgmgr/imgmgr/","text":"Image Manager Description This library accepts incoming image management commands from newtmgr and acts on them. Images can be uploaded, present images listed, and system can be told to switch to another image. Currently the package assumes that there are 2 image slots, one active one and another one in standby. When new image is uploaded, it replaces the one in standby slot. This is the model for scenario when MCU has internal flash only, it executes the code from that flash, and there is enough space to store 2 full images. Image manager interacts with bootloader by telling it to boot to a specific image. At the moment this has to be done by writing a file which contains a version number of the image to boot. Note that image manager itself does not replace the active image. Image manager also can upload files to filesystem as well as download them. Note that commands accessing filesystems (next boot target, file upload/download) will not be available unless project includes filesystem implementation. Data structures N/A. List of Functions The functions available in imgmgr are: Function Description imgr_ver_parse Parses character string containing specified image version number and writes that to given image_version struct. imgr_ver_str Takes version string from specified image_version struct and formats it into a printable string.","title":"toc"},{"location":"os/modules/imgmgr/imgmgr/#image-manager","text":"","title":"Image Manager"},{"location":"os/modules/imgmgr/imgmgr/#description","text":"This library accepts incoming image management commands from newtmgr and acts on them. Images can be uploaded, present images listed, and system can be told to switch to another image. Currently the package assumes that there are 2 image slots, one active one and another one in standby. When new image is uploaded, it replaces the one in standby slot. This is the model for scenario when MCU has internal flash only, it executes the code from that flash, and there is enough space to store 2 full images. Image manager interacts with bootloader by telling it to boot to a specific image. At the moment this has to be done by writing a file which contains a version number of the image to boot. Note that image manager itself does not replace the active image. Image manager also can upload files to filesystem as well as download them. Note that commands accessing filesystems (next boot target, file upload/download) will not be available unless project includes filesystem implementation.","title":"Description"},{"location":"os/modules/imgmgr/imgmgr/#data-structures","text":"N/A.","title":"Data structures"},{"location":"os/modules/imgmgr/imgmgr/#list-of-functions","text":"The functions available in imgmgr are: Function Description imgr_ver_parse Parses character string containing specified image version number and writes that to given image_version struct. imgr_ver_str Takes version string from specified image_version struct and formats it into a printable string.","title":"List of Functions"},{"location":"os/modules/imgmgr/imgmgr_module_init/","text":"imgmgr_module_init void imgmgr_module_init(void) Registers the image manager commands with the mgmt package. sysinit() automatically calls this function during system initialization. Arguments N/A Returned values N/A Notes","title":"Imgmgr module init"},{"location":"os/modules/imgmgr/imgmgr_module_init/#imgmgr_module_init","text":"void imgmgr_module_init(void) Registers the image manager commands with the mgmt package. sysinit() automatically calls this function during system initialization.","title":" imgmgr_module_init "},{"location":"os/modules/imgmgr/imgmgr_module_init/#arguments","text":"N/A","title":"Arguments"},{"location":"os/modules/imgmgr/imgmgr_module_init/#returned-values","text":"N/A","title":"Returned values"},{"location":"os/modules/imgmgr/imgmgr_module_init/#notes","text":"","title":"Notes"},{"location":"os/modules/imgmgr/imgr_ver_parse/","text":"imgr_ver_parse int imgr_ver_parse(char *src, struct image_version *ver) Parses character string containing image version number src and writes that to ver . Version number string should be in format . . . . Major and minor numbers should be within range 0-255, revision between 0-65535 and build_number 0-4294967295. Arguments Arguments Description src Pointer to C string that contains version number being parsed ver Image version number structure containing the returned value Returned values 0 on success and <0 if version number string could not be parsed. Notes Numbers within the string are separated by . . The first number is the major number, and must be provided. Rest of the numbers (minor etc.) are optional. Example int main(int argc, char **argv) { struct image_version hdr_ver; int rc; ... rc = imgr_ver_parse(argv[3], &hdr_ver); if (rc != 0) { print_usage(stderr); return 1; } ... }","title":"imgr_ver_parse"},{"location":"os/modules/imgmgr/imgr_ver_parse/#imgr_ver_parse","text":"int imgr_ver_parse(char *src, struct image_version *ver) Parses character string containing image version number src and writes that to ver . Version number string should be in format . . . . Major and minor numbers should be within range 0-255, revision between 0-65535 and build_number 0-4294967295.","title":" imgr_ver_parse "},{"location":"os/modules/imgmgr/imgr_ver_parse/#arguments","text":"Arguments Description src Pointer to C string that contains version number being parsed ver Image version number structure containing the returned value","title":"Arguments"},{"location":"os/modules/imgmgr/imgr_ver_parse/#returned-values","text":"0 on success and <0 if version number string could not be parsed.","title":"Returned values"},{"location":"os/modules/imgmgr/imgr_ver_parse/#notes","text":"Numbers within the string are separated by . . The first number is the major number, and must be provided. Rest of the numbers (minor etc.) are optional.","title":"Notes"},{"location":"os/modules/imgmgr/imgr_ver_parse/#example","text":"int main(int argc, char **argv) { struct image_version hdr_ver; int rc; ... rc = imgr_ver_parse(argv[3], &hdr_ver); if (rc != 0) { print_usage(stderr); return 1; } ... }","title":"Example"},{"location":"os/modules/imgmgr/imgr_ver_str/","text":"imgr_ver_str int imgr_ver_str(struct image_version *ver, char *dst) Takes the version string from ver and formats that into a printable string to dst . Caller must make sure that dst contains enough space to hold maximum length version string. The convenience defininition for max length version string is named IMGMGR_MAX_VER_STR . Arguments Arguments Description ver Image version number structure containing the value being formatted dst Pointer to C string where results will be stored Returned values Function returns the number of characters filled into the destination string. Notes If build number is 0 in image version structure, it will be left out of the string. Example static void imgr_ver_jsonstr(struct json_encoder *enc, char *key, struct image_version *ver) { char ver_str[IMGMGR_MAX_VER_STR]; int ver_len; ... ver_len = imgr_ver_str(ver, ver_str) ... }","title":"imgr_ver_str"},{"location":"os/modules/imgmgr/imgr_ver_str/#imgr_ver_str","text":"int imgr_ver_str(struct image_version *ver, char *dst) Takes the version string from ver and formats that into a printable string to dst . Caller must make sure that dst contains enough space to hold maximum length version string. The convenience defininition for max length version string is named IMGMGR_MAX_VER_STR .","title":" imgr_ver_str "},{"location":"os/modules/imgmgr/imgr_ver_str/#arguments","text":"Arguments Description ver Image version number structure containing the value being formatted dst Pointer to C string where results will be stored","title":"Arguments"},{"location":"os/modules/imgmgr/imgr_ver_str/#returned-values","text":"Function returns the number of characters filled into the destination string.","title":"Returned values"},{"location":"os/modules/imgmgr/imgr_ver_str/#notes","text":"If build number is 0 in image version structure, it will be left out of the string.","title":"Notes"},{"location":"os/modules/imgmgr/imgr_ver_str/#example","text":"static void imgr_ver_jsonstr(struct json_encoder *enc, char *key, struct image_version *ver) { char ver_str[IMGMGR_MAX_VER_STR]; int ver_len; ... ver_len = imgr_ver_str(ver, ver_str) ... }","title":"Example"},{"location":"os/modules/json/json/","text":"JSON JSON is a data interchange format. The description of this format can be found from IETF RFC 4627. Description This package helps in converting between C data types and JSON data objects. It supports both encoding and decoding. Data structures Encoding /* Encoding functions */ typedef int ( *json_write_func_t )( void *buf , char *data , int len ); struct json_encoder { json_write_func_t je_write ; void *je_arg ; int je_wr_commas: 1 ; char je_encode_buf [ 64 ]; }; Here's the data structure encoder funtions use, and it must be initialized by the caller. The key element is je_write , which is a function pointer which gets called whenever encoding routine is ready with encoded data. The element je_arg is passed to je_write as the first argument. The rest of the structure contents are for internal state management. This function should collect all the data encoder function generates. It can collect this data to a flat buffer, chain of mbufs or even stream through. /** * For encode. The contents of a JSON value to encode. */ struct json_value { uint8_t jv_pad1 ; uint8_t jv_type ; uint16_t jv_len ; union { uint64_t u ; float fl ; char *str ; struct { char **keys ; struct json_value **values ; } composite ; } jv_val ; }; This data structure is filled with data to be encoded. It is best to fill this using the macros JSON_VALUE_STRING() or JSON_VALUE_STRINGN() when value is string, JSON_VALUE_INT() when value is an integer, and so forth. Decoding /* when you implement a json buffer, you must implement these functions */ /* returns the next character in the buffer or '\\0'*/ typedef char ( *json_buffer_read_next_byte_t )( struct json_buffer * ); /* returns the previous character in the buffer or '\\0' */ typedef char ( *json_buffer_read_prev_byte_t )( struct json_buffer * ); /* returns the number of characters read or zero */ typedef int ( *json_buffer_readn_t )( struct json_buffer * , char *buf , int n ); struct json_buffer { json_buffer_readn_t jb_readn ; json_buffer_read_next_byte_t jb_read_next ; json_buffer_read_prev_byte_t jb_read_prev ; }; Function pointers within this structure are used by decoder when it is reading in more data to decode. struct json_attr_t { char *attribute ; json_type type ; union { int *integer ; unsigned int *uinteger ; double *real ; char *string ; bool *boolean ; char *character ; struct json_array_t array ; size_t offset ; } addr ; union { int integer ; unsigned int uinteger ; double real ; bool boolean ; char character ; char *check ; } dflt ; size_t len ; const struct json_enum_t *map ; bool nodefault ; }; This structure tells the decoder about a particular name/value pair. Structure must be filled in before calling the decoder routine json_read_object() . Element Description attribute Name of the value type The type of the variable; see enum json_type addr Contains the address where value should be stored dflt Default value to fill in, if this name is not found len Max number of bytes to read in for value nodefault If set, default value is not copied name List of Functions Functions for encoding: Function Description json_encode_object_start This function starts the encoded JSON object. json_encode_object_key This function writes out a name for a field, followed by \":\" character. json_encode_object_entry This function writes out a name for a field, followed by \":\" character, and the value itself. json_encode_object_finish This function finalizes the encoded JSON object. Functions for decoding: Function Description json_read_object This function reads in JSON data stream, while looking for name/value pairs described in given attribites.","title":"toc"},{"location":"os/modules/json/json/#json","text":"JSON is a data interchange format. The description of this format can be found from IETF RFC 4627.","title":"JSON"},{"location":"os/modules/json/json/#description","text":"This package helps in converting between C data types and JSON data objects. It supports both encoding and decoding.","title":"Description"},{"location":"os/modules/json/json/#data-structures","text":"","title":"Data structures"},{"location":"os/modules/json/json/#encoding","text":"/* Encoding functions */ typedef int ( *json_write_func_t )( void *buf , char *data , int len ); struct json_encoder { json_write_func_t je_write ; void *je_arg ; int je_wr_commas: 1 ; char je_encode_buf [ 64 ]; }; Here's the data structure encoder funtions use, and it must be initialized by the caller. The key element is je_write , which is a function pointer which gets called whenever encoding routine is ready with encoded data. The element je_arg is passed to je_write as the first argument. The rest of the structure contents are for internal state management. This function should collect all the data encoder function generates. It can collect this data to a flat buffer, chain of mbufs or even stream through. /** * For encode. The contents of a JSON value to encode. */ struct json_value { uint8_t jv_pad1 ; uint8_t jv_type ; uint16_t jv_len ; union { uint64_t u ; float fl ; char *str ; struct { char **keys ; struct json_value **values ; } composite ; } jv_val ; }; This data structure is filled with data to be encoded. It is best to fill this using the macros JSON_VALUE_STRING() or JSON_VALUE_STRINGN() when value is string, JSON_VALUE_INT() when value is an integer, and so forth.","title":"Encoding"},{"location":"os/modules/json/json/#decoding","text":"/* when you implement a json buffer, you must implement these functions */ /* returns the next character in the buffer or '\\0'*/ typedef char ( *json_buffer_read_next_byte_t )( struct json_buffer * ); /* returns the previous character in the buffer or '\\0' */ typedef char ( *json_buffer_read_prev_byte_t )( struct json_buffer * ); /* returns the number of characters read or zero */ typedef int ( *json_buffer_readn_t )( struct json_buffer * , char *buf , int n ); struct json_buffer { json_buffer_readn_t jb_readn ; json_buffer_read_next_byte_t jb_read_next ; json_buffer_read_prev_byte_t jb_read_prev ; }; Function pointers within this structure are used by decoder when it is reading in more data to decode. struct json_attr_t { char *attribute ; json_type type ; union { int *integer ; unsigned int *uinteger ; double *real ; char *string ; bool *boolean ; char *character ; struct json_array_t array ; size_t offset ; } addr ; union { int integer ; unsigned int uinteger ; double real ; bool boolean ; char character ; char *check ; } dflt ; size_t len ; const struct json_enum_t *map ; bool nodefault ; }; This structure tells the decoder about a particular name/value pair. Structure must be filled in before calling the decoder routine json_read_object() . Element Description attribute Name of the value type The type of the variable; see enum json_type addr Contains the address where value should be stored dflt Default value to fill in, if this name is not found len Max number of bytes to read in for value nodefault If set, default value is not copied name","title":"Decoding"},{"location":"os/modules/json/json/#list-of-functions","text":"Functions for encoding: Function Description json_encode_object_start This function starts the encoded JSON object. json_encode_object_key This function writes out a name for a field, followed by \":\" character. json_encode_object_entry This function writes out a name for a field, followed by \":\" character, and the value itself. json_encode_object_finish This function finalizes the encoded JSON object. Functions for decoding: Function Description json_read_object This function reads in JSON data stream, while looking for name/value pairs described in given attribites.","title":"List of Functions"},{"location":"os/modules/json/json_encode_object_entry/","text":"json_encode_object_entry int json_encode_object_entry(struct json_encoder *encoder, char *key, struct json_value *val) This function writes out a name for a field, followed by \":\" character, and the value itself. How value is treated depends on the type of the value. Arguments Arguments Description encoder json_encoder to use key name to write out val value to write out Returned values 0 on success. Example static int imgr_list ( struct nmgr_jbuf *njb ) { struct json_encoder *enc ; struct json_value array ; ... json_encode_object_start ( enc ); json_encode_object_entry ( enc , \"images\" , &array ); json_encode_object_finish ( enc ); return 0 ; }","title":"json_encode_object_entry"},{"location":"os/modules/json/json_encode_object_entry/#json_encode_object_entry","text":"int json_encode_object_entry(struct json_encoder *encoder, char *key, struct json_value *val) This function writes out a name for a field, followed by \":\" character, and the value itself. How value is treated depends on the type of the value.","title":" json_encode_object_entry "},{"location":"os/modules/json/json_encode_object_entry/#arguments","text":"Arguments Description encoder json_encoder to use key name to write out val value to write out","title":"Arguments"},{"location":"os/modules/json/json_encode_object_entry/#returned-values","text":"0 on success.","title":"Returned values"},{"location":"os/modules/json/json_encode_object_entry/#example","text":"static int imgr_list ( struct nmgr_jbuf *njb ) { struct json_encoder *enc ; struct json_value array ; ... json_encode_object_start ( enc ); json_encode_object_entry ( enc , \"images\" , &array ); json_encode_object_finish ( enc ); return 0 ; }","title":"Example"},{"location":"os/modules/json/json_encode_object_finish/","text":"json_encode_object_finish int json_encode_object_finish(struct json_encoder *encoder) This function finalizes the encoded JSON object. This means writing out the last \"}\" character. Arguments Arguments Description encoder json_encoder to use Returned values 0 on success. Example static int imgr_list ( struct nmgr_jbuf *njb ) { struct json_encoder *enc ; struct json_value array ; ... json_encode_object_start ( enc ); json_encode_object_entry ( enc , \"images\" , &array ); json_encode_object_finish ( enc ); return 0 ; }","title":"json_encode_object_finish"},{"location":"os/modules/json/json_encode_object_finish/#json_encode_object_finish","text":"int json_encode_object_finish(struct json_encoder *encoder) This function finalizes the encoded JSON object. This means writing out the last \"}\" character.","title":" json_encode_object_finish "},{"location":"os/modules/json/json_encode_object_finish/#arguments","text":"Arguments Description encoder json_encoder to use","title":"Arguments"},{"location":"os/modules/json/json_encode_object_finish/#returned-values","text":"0 on success.","title":"Returned values"},{"location":"os/modules/json/json_encode_object_finish/#example","text":"static int imgr_list ( struct nmgr_jbuf *njb ) { struct json_encoder *enc ; struct json_value array ; ... json_encode_object_start ( enc ); json_encode_object_entry ( enc , \"images\" , &array ); json_encode_object_finish ( enc ); return 0 ; }","title":"Example"},{"location":"os/modules/json/json_encode_object_key/","text":"json_encode_object_key int json_encode_object_key(struct json_encoder *encoder, char *key) This function writes out a name for a field, followed by \":\" character. You would use this e.g. when the value that follows is a JSON object. Arguments Arguments Description encoder json_encoder to use key name to write out Returned values 0 on success. Example int nmgr_def_taskstat_read ( struct nmgr_jbuf *njb ) { ... struct json_value jv ; json_encode_object_start ( &njb->njb_enc ); JSON_VALUE_INT ( &jv , NMGR_ERR_EOK ); json_encode_object_entry ( &njb->njb_enc , \"rc\" , &jv ); json_encode_object_key ( &njb->njb_enc , \"tasks\" ); json_encode_object_start ( &njb->njb_enc ); ... }","title":"json_encode_object_key"},{"location":"os/modules/json/json_encode_object_key/#json_encode_object_key","text":"int json_encode_object_key(struct json_encoder *encoder, char *key) This function writes out a name for a field, followed by \":\" character. You would use this e.g. when the value that follows is a JSON object.","title":" json_encode_object_key "},{"location":"os/modules/json/json_encode_object_key/#arguments","text":"Arguments Description encoder json_encoder to use key name to write out","title":"Arguments"},{"location":"os/modules/json/json_encode_object_key/#returned-values","text":"0 on success.","title":"Returned values"},{"location":"os/modules/json/json_encode_object_key/#example","text":"int nmgr_def_taskstat_read ( struct nmgr_jbuf *njb ) { ... struct json_value jv ; json_encode_object_start ( &njb->njb_enc ); JSON_VALUE_INT ( &jv , NMGR_ERR_EOK ); json_encode_object_entry ( &njb->njb_enc , \"rc\" , &jv ); json_encode_object_key ( &njb->njb_enc , \"tasks\" ); json_encode_object_start ( &njb->njb_enc ); ... }","title":"Example"},{"location":"os/modules/json/json_encode_object_start/","text":"json_encode_object_start int json_encode_object_start(struct json_encoder *encoder) This function starts the encoded JSON object. Usually this means writing out the initial \"{\" character. Arguments Arguments Description encoder json_encoder to use Returned values 0 on success. Example static int imgr_list ( struct nmgr_jbuf *njb ) { struct json_encoder *enc ; struct json_value array ; ... json_encode_object_start ( enc ); json_encode_object_entry ( enc , \"images\" , &array ); json_encode_object_finish ( enc ); return 0 ; }","title":"json_encode_object_start"},{"location":"os/modules/json/json_encode_object_start/#json_encode_object_start","text":"int json_encode_object_start(struct json_encoder *encoder) This function starts the encoded JSON object. Usually this means writing out the initial \"{\" character.","title":" json_encode_object_start "},{"location":"os/modules/json/json_encode_object_start/#arguments","text":"Arguments Description encoder json_encoder to use","title":"Arguments"},{"location":"os/modules/json/json_encode_object_start/#returned-values","text":"0 on success.","title":"Returned values"},{"location":"os/modules/json/json_encode_object_start/#example","text":"static int imgr_list ( struct nmgr_jbuf *njb ) { struct json_encoder *enc ; struct json_value array ; ... json_encode_object_start ( enc ); json_encode_object_entry ( enc , \"images\" , &array ); json_encode_object_finish ( enc ); return 0 ; }","title":"Example"},{"location":"os/modules/json/json_read_object/","text":"json_read_object int json_read_object(struct json_buffer *jb, const struct json_attr_t *attrs) This function reads in JSON data stream, while looking for name/value pairs described in attrs . attrs is an array; end of the array is indicated by an entry with NULL as the name. Arguments Arguments Description jb json_decoder to use attrs array of attributes to look for Returned values 0 on success. Example static int imgr_upload ( struct nmgr_jbuf *njb ) { ... const struct json_attr_t off_attr [ 4 ] = { [ 0 ] = { . attribute = \"off\" , . type = t_uinteger , . addr . uinteger = &off , . nodefault = true }, [ 1 ] = { . attribute = \"data\" , . type = t_string , . addr . string = img_data , . len = sizeof ( img_data ) }, [ 2 ] = { . attribute = \"len\" , . type = t_uinteger , . addr . uinteger = &size , . nodefault = true } }; ... rc = json_read_object ( &njb->njb_buf , off_attr ); if ( rc || off == UINT_MAX ) { rc = OS_EINVAL ; goto err ; } ... }","title":"json_read_object"},{"location":"os/modules/json/json_read_object/#json_read_object","text":"int json_read_object(struct json_buffer *jb, const struct json_attr_t *attrs) This function reads in JSON data stream, while looking for name/value pairs described in attrs . attrs is an array; end of the array is indicated by an entry with NULL as the name.","title":" json_read_object "},{"location":"os/modules/json/json_read_object/#arguments","text":"Arguments Description jb json_decoder to use attrs array of attributes to look for","title":"Arguments"},{"location":"os/modules/json/json_read_object/#returned-values","text":"0 on success.","title":"Returned values"},{"location":"os/modules/json/json_read_object/#example","text":"static int imgr_upload ( struct nmgr_jbuf *njb ) { ... const struct json_attr_t off_attr [ 4 ] = { [ 0 ] = { . attribute = \"off\" , . type = t_uinteger , . addr . uinteger = &off , . nodefault = true }, [ 1 ] = { . attribute = \"data\" , . type = t_string , . addr . string = img_data , . len = sizeof ( img_data ) }, [ 2 ] = { . attribute = \"len\" , . type = t_uinteger , . addr . uinteger = &size , . nodefault = true } }; ... rc = json_read_object ( &njb->njb_buf , off_attr ); if ( rc || off == UINT_MAX ) { rc = OS_EINVAL ; goto err ; } ... }","title":"Example"},{"location":"os/modules/logs/logs/","text":"Logging Mynewt log package supports logging of information within a Mynewt application. It allows packages to define their own log streams with separate names. It also allows an application to control the output destination of logs. Description In the Mynewt OS, the log package comes in two versions: The sys/log/full package implements the complete log functionality and API. The sys/log/stub package implements stubs for the API. Both packages export the log API, and any package that uses the log API must list log as a requirement in its pkg.yml file as follows: pkg.req_apis: - log The application's pkg.yml file specifies the version of the log package to use. A project that requires the full logging capability must list the sys/log/full package as a dependency in its pkg.yml file: pkg.deps: - sys/log/full You can use the sys/log/stub package if you want to build your application without logging to reduce code size. Compile Time Settings To save space at compile time, there is a compile time log level that includes/excludes certain logs at compile time, saving image space. For example, during debug, you can have significant logs present, but disable these at compile time to ensure the code size limits are met. A compiler flag LOG_LEVEL can be set in your target.cflags or within your app pkg.cflags files to set the compile time log level. The log level are defined in /sys/log/full/include/log/log.h but must be added by number to your yml file. For example: pkg.cflags -DLOG_LEVEL=3 or newt target set my_target cflags=-DLOG_LEVEL=3 would both set the compile-time log level to LOG_LEVEL_ERROR . All logs of less than LOG_LEVEL_ERROR severity would be disabled at compile time and take no space within the Mynewt application image. These compile time settings are applicable to all logs registered with the system. Log Each log stream requires a log structure to define its logging properties. Log Handler To use logs, a log handler that handles the I/O from the log is required. The log package comes with three pre-built log handlers: console -- streams log events directly to the console port. Does not support walking and reading. cbmem -- writes/reads log events to a circular buffer. Supports walking and reading for access by newtmgr and shell commands. fcb -- writes/reads log events to a flash circular buffer . Supports walking and reading for access by newtmgr and shell commands. In addition, it is possible to create custom log handlers for other methods. Examples may include Flash file system Flat flash buffer Streamed over some other interface To use logging, you typically do not need to create your own log handler. You can use one of the pre-built ones. A package or an application must define a variable of type struct log and register a log handler for it with the log package. It must call the log_register() function to specify the log handler to use: log_register ( char *name , struct log *log , const struct log_handler *lh , void *arg , uint8_t level ) The parameters are: name - Name of the log stream. log - Log instance to register, lh - Pointer to the log handler. You can specify one of the pre-built ones: &log_console_handler for console &log_cbm_handler for circular buffer &log_fcb_handler for flash circular buffer arg - Opaque argument that the specified log handler uses. The value of this argument depends on the log handler you specify: NULL for the log_console_handler . Pointer to an initialized cbmem structure (see util/cbmem package) for the log_cbm_handler . Pointer to an initialized fcb_log structure (see fs/fcb package) for the log_fcb_handler . Typically, a package that uses logging defines a global variable, such as my_package_log , of type struct log . The package can call the log_register() function with default values, but usually an application will override the logging properties and where to log to. There are two ways a package can allow an application to override the values: Define system configuration settings that an application can set and the package can then call the log_register() function with the configuration values. Make the my_package_log variable external and let the application call the log_register() function to specify a log handler for its specific purpose. Configuring Logging for Packages that an Application Uses Here is an example of how an application can set the log handlers for the logs of the packages that the application includes. In this example, the package1 package defines the variable package1_log of type struct log and externs the variable. Similarly, the package2 package defines the variable package2_log and externs the variable. The application sets logs for package1 to use console and sets logs for package2 to use a circular buffer. #include <package1/package1.h> #include <package2/package2.h> #include <util/cbmem.h> #include <log/log.h> static uint32_t cbmem_buf [ MAX_CBMEM_BUF ]; static struct cbmem cbmem ; void app_log_init ( void ) { log_register ( \"package1_log\" , &package1_log , &log_console_handler , NULL , LOG_SYSLEVEL ); cbmem_init ( &cbmem , cbmem_buf , MAX_CBMEM_BUF ); log_register ( \"package2_log\" , &package2_log , &log_cbmem_handler , &cbmem , LOG_SYSLEVEL ); } Implementing a Package that Uses Logging This example shows how a package logs to console. The package registers default logging properties to use the console, but allows an application to override the values. It defines the my_package_log variable and makes it external so an application can override log handler. Make the my_package_log variable external: /* my_package.h*/ /* pick a unique name here */ extern struct log my_package_log ; Define the my_package_log variable and register the console log handler: /* my_package.c */ struct log my_package_log ; { ... /* register my log with a name to the system */ log_register ( \"log\" , &my_package_log , &log_console_handler , NULL , LOG_LEVEL_DEBUG ); LOG_DEBUG ( &my_package_log , LOG_MODULE_DEFAULT , \"bla\" ); LOG_DEBUG ( &my_package_log , LOG_MODULE_DEFAULT , \"bab\" ); } Log API and Log Levels For more information on the log API and log levels, see the sys/log/full/include/log/log.h header file.","title":"toc"},{"location":"os/modules/logs/logs/#logging","text":"Mynewt log package supports logging of information within a Mynewt application. It allows packages to define their own log streams with separate names. It also allows an application to control the output destination of logs.","title":"Logging"},{"location":"os/modules/logs/logs/#description","text":"In the Mynewt OS, the log package comes in two versions: The sys/log/full package implements the complete log functionality and API. The sys/log/stub package implements stubs for the API. Both packages export the log API, and any package that uses the log API must list log as a requirement in its pkg.yml file as follows: pkg.req_apis: - log The application's pkg.yml file specifies the version of the log package to use. A project that requires the full logging capability must list the sys/log/full package as a dependency in its pkg.yml file: pkg.deps: - sys/log/full You can use the sys/log/stub package if you want to build your application without logging to reduce code size.","title":"Description"},{"location":"os/modules/logs/logs/#compile-time-settings","text":"To save space at compile time, there is a compile time log level that includes/excludes certain logs at compile time, saving image space. For example, during debug, you can have significant logs present, but disable these at compile time to ensure the code size limits are met. A compiler flag LOG_LEVEL can be set in your target.cflags or within your app pkg.cflags files to set the compile time log level. The log level are defined in /sys/log/full/include/log/log.h but must be added by number to your yml file. For example: pkg.cflags -DLOG_LEVEL=3 or newt target set my_target cflags=-DLOG_LEVEL=3 would both set the compile-time log level to LOG_LEVEL_ERROR . All logs of less than LOG_LEVEL_ERROR severity would be disabled at compile time and take no space within the Mynewt application image. These compile time settings are applicable to all logs registered with the system.","title":"Compile Time Settings"},{"location":"os/modules/logs/logs/#log","text":"Each log stream requires a log structure to define its logging properties.","title":"Log"},{"location":"os/modules/logs/logs/#log-handler","text":"To use logs, a log handler that handles the I/O from the log is required. The log package comes with three pre-built log handlers: console -- streams log events directly to the console port. Does not support walking and reading. cbmem -- writes/reads log events to a circular buffer. Supports walking and reading for access by newtmgr and shell commands. fcb -- writes/reads log events to a flash circular buffer . Supports walking and reading for access by newtmgr and shell commands. In addition, it is possible to create custom log handlers for other methods. Examples may include Flash file system Flat flash buffer Streamed over some other interface To use logging, you typically do not need to create your own log handler. You can use one of the pre-built ones. A package or an application must define a variable of type struct log and register a log handler for it with the log package. It must call the log_register() function to specify the log handler to use: log_register ( char *name , struct log *log , const struct log_handler *lh , void *arg , uint8_t level ) The parameters are: name - Name of the log stream. log - Log instance to register, lh - Pointer to the log handler. You can specify one of the pre-built ones: &log_console_handler for console &log_cbm_handler for circular buffer &log_fcb_handler for flash circular buffer arg - Opaque argument that the specified log handler uses. The value of this argument depends on the log handler you specify: NULL for the log_console_handler . Pointer to an initialized cbmem structure (see util/cbmem package) for the log_cbm_handler . Pointer to an initialized fcb_log structure (see fs/fcb package) for the log_fcb_handler . Typically, a package that uses logging defines a global variable, such as my_package_log , of type struct log . The package can call the log_register() function with default values, but usually an application will override the logging properties and where to log to. There are two ways a package can allow an application to override the values: Define system configuration settings that an application can set and the package can then call the log_register() function with the configuration values. Make the my_package_log variable external and let the application call the log_register() function to specify a log handler for its specific purpose.","title":"Log Handler"},{"location":"os/modules/logs/logs/#configuring-logging-for-packages-that-an-application-uses","text":"Here is an example of how an application can set the log handlers for the logs of the packages that the application includes. In this example, the package1 package defines the variable package1_log of type struct log and externs the variable. Similarly, the package2 package defines the variable package2_log and externs the variable. The application sets logs for package1 to use console and sets logs for package2 to use a circular buffer. #include <package1/package1.h> #include <package2/package2.h> #include <util/cbmem.h> #include <log/log.h> static uint32_t cbmem_buf [ MAX_CBMEM_BUF ]; static struct cbmem cbmem ; void app_log_init ( void ) { log_register ( \"package1_log\" , &package1_log , &log_console_handler , NULL , LOG_SYSLEVEL ); cbmem_init ( &cbmem , cbmem_buf , MAX_CBMEM_BUF ); log_register ( \"package2_log\" , &package2_log , &log_cbmem_handler , &cbmem , LOG_SYSLEVEL ); }","title":"Configuring Logging for Packages that an Application Uses"},{"location":"os/modules/logs/logs/#implementing-a-package-that-uses-logging","text":"This example shows how a package logs to console. The package registers default logging properties to use the console, but allows an application to override the values. It defines the my_package_log variable and makes it external so an application can override log handler. Make the my_package_log variable external: /* my_package.h*/ /* pick a unique name here */ extern struct log my_package_log ; Define the my_package_log variable and register the console log handler: /* my_package.c */ struct log my_package_log ; { ... /* register my log with a name to the system */ log_register ( \"log\" , &my_package_log , &log_console_handler , NULL , LOG_LEVEL_DEBUG ); LOG_DEBUG ( &my_package_log , LOG_MODULE_DEFAULT , \"bla\" ); LOG_DEBUG ( &my_package_log , LOG_MODULE_DEFAULT , \"bab\" ); }","title":"Implementing a Package that Uses Logging"},{"location":"os/modules/logs/logs/#log-api-and-log-levels","text":"For more information on the log API and log levels, see the sys/log/full/include/log/log.h header file.","title":"Log API and Log Levels"},{"location":"os/modules/shell/shell/","text":"Shell The shell runs above the console and provides two functionalities: Processes console input. See the Enabling the Console and Shell Tutorial for an example of the shell. Implements the newtmgr line protocol over serial transport. The sys/shell package implements the shell. The shell uses the OS default event queue for shell events and runs in the context of the main task. An application can, optionally, specify a dedicated event queue for the shell to use. Description The shell's first job is to direct incoming commands to other subsystems. It parses the incoming character string into tokens and uses the first token to determine the subsystem command handler to call to process the command. Subsystems register their command handlers using the shell_cmd_register() function. When shell calls the command handler, it passes the other tokens as arguments. A few commands are currently available in the shell - tasks , log , echo , date and prompt . The shell's second job is to handle packet framing, encoding, and decoding of newtmgr protocol messages that are sent over the console. The Newtmgr serial transport package ( mgmt/newtmgr/transport/newtmgr_shell ) calls the shell_nlip_input_register() function to register a handler that the shell calls when it receives newtmgr request messages. Data structures This data structure is used in holding information about registered command handlers. struct shell_cmd { char *sc_cmd ; shell_cmd_func_t sc_cmd_func ; STAILQ_ENTRY ( shell_cmd ) sc_next ; }; Element Description sc_cmd Character string of the command sc_cmd_func Pointer to the command handler sc_next Bookkeeping linkage internal for shell List of Functions The functions available in this OS feature are: Function Description shell_cmd_register Registers a handler for incoming console commands. shell_nlip_input_register Registers a handler for incoming newtmgr messages. shell_nlip_output Queue outgoing newtmgr message for transmission. shell_evq_set Specifies a dedicated event queue for shell events.","title":"toc"},{"location":"os/modules/shell/shell/#shell","text":"The shell runs above the console and provides two functionalities: Processes console input. See the Enabling the Console and Shell Tutorial for an example of the shell. Implements the newtmgr line protocol over serial transport. The sys/shell package implements the shell. The shell uses the OS default event queue for shell events and runs in the context of the main task. An application can, optionally, specify a dedicated event queue for the shell to use.","title":"Shell"},{"location":"os/modules/shell/shell/#description","text":"The shell's first job is to direct incoming commands to other subsystems. It parses the incoming character string into tokens and uses the first token to determine the subsystem command handler to call to process the command. Subsystems register their command handlers using the shell_cmd_register() function. When shell calls the command handler, it passes the other tokens as arguments. A few commands are currently available in the shell - tasks , log , echo , date and prompt . The shell's second job is to handle packet framing, encoding, and decoding of newtmgr protocol messages that are sent over the console. The Newtmgr serial transport package ( mgmt/newtmgr/transport/newtmgr_shell ) calls the shell_nlip_input_register() function to register a handler that the shell calls when it receives newtmgr request messages.","title":"Description"},{"location":"os/modules/shell/shell/#data-structures","text":"This data structure is used in holding information about registered command handlers. struct shell_cmd { char *sc_cmd ; shell_cmd_func_t sc_cmd_func ; STAILQ_ENTRY ( shell_cmd ) sc_next ; }; Element Description sc_cmd Character string of the command sc_cmd_func Pointer to the command handler sc_next Bookkeeping linkage internal for shell","title":"Data structures"},{"location":"os/modules/shell/shell/#list-of-functions","text":"The functions available in this OS feature are: Function Description shell_cmd_register Registers a handler for incoming console commands. shell_nlip_input_register Registers a handler for incoming newtmgr messages. shell_nlip_output Queue outgoing newtmgr message for transmission. shell_evq_set Specifies a dedicated event queue for shell events.","title":"List of Functions"},{"location":"os/modules/shell/shell_cmd_register/","text":"shell_cmd_register int shell_cmd_register ( struct shell_cmd *sc ) Registers a handler for incoming console commands. Within the structure there is the command string and the handler for those commands. Caller must allocate the memory for this structure and keep it around as shell links this to its own internal data structures. Command handler is of type int(*shell_cmd_func_t)(int argc, char **argv) . Command line arguments are passed to it as an array of character pointers. Arguments Arguments Description sc Structure containing info about the command. Returned values Returns 0 on success. Non-zero on failure. Example static int fs_ls_cmd ( int argc , char **argv ); static struct shell_cmd fs_ls_struct = { . sc_cmd = \"ls\" , . sc_cmd_func = fs_ls_cmd }; void fs_cli_init ( void ) { shell_cmd_register ( &fs_ls_struct ); .... }","title":"shell_cmd_register"},{"location":"os/modules/shell/shell_cmd_register/#shell_cmd_register","text":"int shell_cmd_register ( struct shell_cmd *sc ) Registers a handler for incoming console commands. Within the structure there is the command string and the handler for those commands. Caller must allocate the memory for this structure and keep it around as shell links this to its own internal data structures. Command handler is of type int(*shell_cmd_func_t)(int argc, char **argv) . Command line arguments are passed to it as an array of character pointers.","title":" shell_cmd_register "},{"location":"os/modules/shell/shell_cmd_register/#arguments","text":"Arguments Description sc Structure containing info about the command.","title":"Arguments"},{"location":"os/modules/shell/shell_cmd_register/#returned-values","text":"Returns 0 on success. Non-zero on failure.","title":"Returned values"},{"location":"os/modules/shell/shell_cmd_register/#example","text":"static int fs_ls_cmd ( int argc , char **argv ); static struct shell_cmd fs_ls_struct = { . sc_cmd = \"ls\" , . sc_cmd_func = fs_ls_cmd }; void fs_cli_init ( void ) { shell_cmd_register ( &fs_ls_struct ); .... }","title":"Example"},{"location":"os/modules/shell/shell_evq_set/","text":"shell_evq_set void shell_evq_set ( struct os_eventq *evq ) Specifies an event queue to use for shell events. You must create the event queue and the task to process events from the queue before calling this function. By default, shell uses the OS default event queue and executes in the context of the main task that Mynewt creates. Arguments Arguments Description evq Pointer to the event queue to use for shell events. Returned values None Notes","title":"shell_evq_set"},{"location":"os/modules/shell/shell_evq_set/#shell_evq_set","text":"void shell_evq_set ( struct os_eventq *evq ) Specifies an event queue to use for shell events. You must create the event queue and the task to process events from the queue before calling this function. By default, shell uses the OS default event queue and executes in the context of the main task that Mynewt creates.","title":" shell_evq_set"},{"location":"os/modules/shell/shell_evq_set/#arguments","text":"Arguments Description evq Pointer to the event queue to use for shell events.","title":"Arguments"},{"location":"os/modules/shell/shell_evq_set/#returned-values","text":"None","title":"Returned values"},{"location":"os/modules/shell/shell_evq_set/#notes","text":"","title":"Notes"},{"location":"os/modules/shell/shell_nlip_input_register/","text":"shell_nlip_input_register int shell_nlip_input_register ( shell_nlip_input_func_t nf , void *arg ) Registers a handler for incoming newtmgr messages. Shell receives incoming data stream from UART and when it detects NLIP frame, it decodes it and passes it on by calling the function nf . Handler function is of type int (*shell_nlip_input_func_t)(struct os_mbuf *m, void *arg) . Shell passes the incoming newtmgr message inside os_mbuf m , and arg is the argument that was passed in during handler registration. Arguments Arguments Description nf Handler for incoming newtmgr datagrams. arg Argument that gets passed to this handler, along with the datagram Returned values Returns 0 on success. Example static int nmgr_shell_in ( struct os_mbuf *m , void *arg ) { .... } int nmgr_task_init ( uint8_t prio , os_stack_t *stack_ptr , uint16_t stack_len ) { int rc ; .... rc = shell_nlip_input_register ( nmgr_shell_in , ( void * ) &g_nmgr_shell_transport ); if ( rc != 0 ) { goto err ; } .... }","title":"shell_nlip_input_register"},{"location":"os/modules/shell/shell_nlip_input_register/#shell_nlip_input_register","text":"int shell_nlip_input_register ( shell_nlip_input_func_t nf , void *arg ) Registers a handler for incoming newtmgr messages. Shell receives incoming data stream from UART and when it detects NLIP frame, it decodes it and passes it on by calling the function nf . Handler function is of type int (*shell_nlip_input_func_t)(struct os_mbuf *m, void *arg) . Shell passes the incoming newtmgr message inside os_mbuf m , and arg is the argument that was passed in during handler registration.","title":" shell_nlip_input_register "},{"location":"os/modules/shell/shell_nlip_input_register/#arguments","text":"Arguments Description nf Handler for incoming newtmgr datagrams. arg Argument that gets passed to this handler, along with the datagram","title":"Arguments"},{"location":"os/modules/shell/shell_nlip_input_register/#returned-values","text":"Returns 0 on success.","title":"Returned values"},{"location":"os/modules/shell/shell_nlip_input_register/#example","text":"static int nmgr_shell_in ( struct os_mbuf *m , void *arg ) { .... } int nmgr_task_init ( uint8_t prio , os_stack_t *stack_ptr , uint16_t stack_len ) { int rc ; .... rc = shell_nlip_input_register ( nmgr_shell_in , ( void * ) &g_nmgr_shell_transport ); if ( rc != 0 ) { goto err ; } .... }","title":"Example"},{"location":"os/modules/shell/shell_nlip_output/","text":"shell_nlip_output int shell_nlip_output ( struct os_mbuf *m ) Queue outgoing newtmgr message for transmission. Shell package will encode this and frame it while sending it out via console. Arguments Arguments Description m os_mbuf containing the message Returned values Returns 0 on success. Example static int nmgr_shell_out ( struct nmgr_transport *nt , struct os_mbuf *m ) { int rc ; rc = shell_nlip_output ( m ); if ( rc != 0 ) { goto err ; } return ( 0 ); err : return ( rc ); }","title":"shell_nlip_output"},{"location":"os/modules/shell/shell_nlip_output/#shell_nlip_output","text":"int shell_nlip_output ( struct os_mbuf *m ) Queue outgoing newtmgr message for transmission. Shell package will encode this and frame it while sending it out via console.","title":" shell_nlip_output "},{"location":"os/modules/shell/shell_nlip_output/#arguments","text":"Arguments Description m os_mbuf containing the message","title":"Arguments"},{"location":"os/modules/shell/shell_nlip_output/#returned-values","text":"Returns 0 on success.","title":"Returned values"},{"location":"os/modules/shell/shell_nlip_output/#example","text":"static int nmgr_shell_out ( struct nmgr_transport *nt , struct os_mbuf *m ) { int rc ; rc = shell_nlip_output ( m ); if ( rc != 0 ) { goto err ; } return ( 0 ); err : return ( rc ); }","title":"Example"},{"location":"os/modules/shell/shell_task_init/","text":"shell_task_init int shell_task_init ( uint8_t prio , os_stack_t *stack , uint16_t stack_size , int max_input_length ); Initializes the shell package. This creates a task for shell, and registers a few commands on its own ( echo , ? , prompt for example). It also allocates memory for buffering console input. Arguments Arguments Description prio Priority of the shell task stack Pointer to shell tasks's stack stack_size Size of the aforementioned stack (in units of os_stack_t) max_input_length the maximum expected length of line for input Returned values Returns 0 on success; nonzero on failure. Notes You can register commands before calling this, but only if OS has not been started. Example Here's an example of stand-alone code which allows the user to execute regression tests for sys/config package only. #define SHELL_TASK_PRIO (3) #define SHELL_MAX_INPUT_LEN (256) #define SHELL_TASK_STACK_SIZE (OS_STACK_ALIGN(384)) os_stack_t shell_stack [ SHELL_TASK_STACK_SIZE ]; int main ( int argc , char **argv ) { .... shell_task_init ( SHELL_TASK_PRIO , shell_stack , SHELL_TASK_STACK_SIZE , SHELL_MAX_INPUT_LEN ); .... }","title":"Shell task init"},{"location":"os/modules/shell/shell_task_init/#shell_task_init","text":"int shell_task_init ( uint8_t prio , os_stack_t *stack , uint16_t stack_size , int max_input_length ); Initializes the shell package. This creates a task for shell, and registers a few commands on its own ( echo , ? , prompt for example). It also allocates memory for buffering console input.","title":" shell_task_init"},{"location":"os/modules/shell/shell_task_init/#arguments","text":"Arguments Description prio Priority of the shell task stack Pointer to shell tasks's stack stack_size Size of the aforementioned stack (in units of os_stack_t) max_input_length the maximum expected length of line for input","title":"Arguments"},{"location":"os/modules/shell/shell_task_init/#returned-values","text":"Returns 0 on success; nonzero on failure.","title":"Returned values"},{"location":"os/modules/shell/shell_task_init/#notes","text":"You can register commands before calling this, but only if OS has not been started.","title":"Notes"},{"location":"os/modules/shell/shell_task_init/#example","text":"Here's an example of stand-alone code which allows the user to execute regression tests for sys/config package only. #define SHELL_TASK_PRIO (3) #define SHELL_MAX_INPUT_LEN (256) #define SHELL_TASK_STACK_SIZE (OS_STACK_ALIGN(384)) os_stack_t shell_stack [ SHELL_TASK_STACK_SIZE ]; int main ( int argc , char **argv ) { .... shell_task_init ( SHELL_TASK_PRIO , shell_stack , SHELL_TASK_STACK_SIZE , SHELL_MAX_INPUT_LEN ); .... }","title":"Example"},{"location":"os/modules/split/split/","text":"Split Images Description The split image mechanism divides a target into two separate images: one capable of image upgrade; the other containing application code. By isolating upgrade functionality to a separate image, the application can support over-the-air upgrade without dedicating flash space to network stack and management code. Concept Mynewt supports three image setups: Setup Description Single One large image; upgrade not supported. Unified Two standalone images. Split Kernel in slot 0; application in slot 1. Each setup has its tradeoffs. The Single setup gives you the most flash space, but doesn't allow you to upgrade after manufacturing. The Unified setup allows for a complete failover in case a bad image gets uploaded, but requires a lot of redundancy in each image, limiting the amount of flash available to the application. The Split setup sits somewhere between these two options. Before exploring the split setup in more detail, it might be helpful to get a basic understanding of the Mynewt boot sequence. The boot process is summarized below. Boot Sequence - Single In the Single setup, there is no boot loader. Instead, the image is placed at address 0. The hardware boots directly into the image code. Upgrade is not possible because there is no boot loader to move an alternate image into place. Boot Sequence - Unified In the Unified setup, the boot loader is placed at address 0. At startup, the boot loader arranges for the correct image to be in image slot 0, which may entail swapping the contents of the two image slots. Finally, the boot loader jumps to the image in slot 0. Boot Sequence - Split The Split setup differs from the other setups mainly in that a target is not fully contained in a single image. Rather, the target is partitioned among two separate images: the loader , and the application . Functionality is divided among these two images as follows: Loader: Mynewt OS. Network stack for connectivity during upgrade e.g. BLE stack. Anything else required for image upgrade. Application: Parts of Mynewt not required for image upgrade. Application-specific code. The loader image serves three purposes: Second-stage boot loader: it jumps into the application image at start up. Image upgrade server: the user can upgrade to a new loader + application combo, even if an application image is not currently running. Functionality container: the application image can directly access all the code present in the loader image From the perspective of the boot loader, a loader image is identical to a plain unified image. What makes a loader image different is a change to its start up sequence: rather than starting the Mynewt OS, it jumps to the application image in slot 1 if one is present. Tutorial Building a Split Image We will be referring to the nRF51dk for examples in this document. Let's take a look at this board's flash map (defined in hw/bsp/nrf51dk/bsp.yml ): Name Offset Size (kB) Boot loader 0x00000000 16 Reboot log 0x00004000 16 Image slot 0 0x00008000 110 Image slot 1 0x00023800 110 Image scratch 0x0003f000 2 Flash file system 0x0003f800 2 The application we will be building is bleprph . First, we create a target to tie our BSP and application together. newt target create bleprph-nrf51dk newt target set bleprph-nrf51dk \\ app=@apache-mynewt-core/apps/bleprph \\ bsp=@apache-mynewt-core/hw/bsp/nrf51dk \\ build_profile=optimized \\ syscfg=BLE_LL_CFG_FEAT_LE_ENCRYPTION=0:BLE_SM_LEGACY=0 The two syscfg settings disable bluetooth security and keep the code size down. We can verify the target using the target show command: [~/tmp/myproj2]$ newt target show bleprph-nrf51dk targets/bleprph-nrf51dk app=@apache-mynewt-core/apps/bleprph bsp=@apache-mynewt-core/hw/bsp/nrf51dk build_profile=optimized syscfg=BLE_LL_CFG_FEAT_LE_ENCRYPTION=0:BLE_SM_LEGACY=0 Next, build the target: [~/tmp/myproj2]$ newt build bleprph-nrf51dk Building target targets/bleprph-nrf51dk # [...] Target successfully built: targets/bleprph-nrf51dk With our target built, we can view a code size breakdown using the newt size <target> command. In the interest of brevity, the smaller entries are excluded from the below output: [~/tmp/myproj2]$ newt size bleprph-nrf51dk Size of Application Image: app FLASH RAM 2446 1533 apps_bleprph.a 1430 104 boot_bootutil.a 1232 0 crypto_mbedtls.a 1107 0 encoding_cborattr.a 2390 0 encoding_tinycbor.a 1764 0 fs_fcb.a 2959 697 hw_drivers_nimble_nrf51.a 4126 108 hw_mcu_nordic_nrf51xxx.a 8161 4049 kernel_os.a 2254 38 libc_baselibc.a 2612 0 libgcc.a 2232 24 mgmt_imgmgr.a 1499 44 mgmt_newtmgr_nmgr_os.a 23918 1930 net_nimble_controller.a 28537 2779 net_nimble_host.a 2207 205 sys_config.a 1074 197 sys_console_full.a 3268 97 sys_log.a 1296 0 time_datetime.a objsize text data bss dec hex filename 105592 1176 13392 120160 1d560 /home/me/tmp/myproj2/bin/targets/bleprph-nrf51dk/app/apps/bleprph/bleprph.elf The full image text size is about 103kB (where 1kB = 1024 bytes). With an image slot size of 110kB, this leaves only about 7kB of flash for additional application code and data. Not good. This is the situation we would be facing if we were using the Unified setup. The Split setup can go a long way in solving our problem. Our unified bleprph image consists mostly of components that get used during an image upgrade. By using the Split setup, we turn the unified image into two separate images: the loader and the application. The functionality related to image upgrade can be delegated to the loader image, freeing up a significant amount of flash in the application image slot. Let's create a new target to use with the Split setup. We designate a target as a split target by setting the loader variable. In our example, we are going to use bleprph as the loader, and splitty as the application. bleprph makes sense as a loader because it contains the BLE stack and everything else required for an image upgrade. newt target create split-nrf51dk newt target set split-nrf51dk \\ loader=@apache-mynewt-core/apps/bleprph \\ app=@apache-mynewt-core/apps/splitty \\ bsp=@apache-mynewt-core/hw/bsp/nrf51dk \\ build_profile=optimized \\ syscfg=BLE_LL_CFG_FEAT_LE_ENCRYPTION=0:BLE_SM_LEGACY=0 Verify that the target looks correct: [~/tmp/myproj2]$ newt target show split-nrf51dk targets/split-nrf51dk app=@apache-mynewt-core/apps/splitty bsp=@apache-mynewt-core/hw/bsp/nrf51dk build_profile=optimized loader=@apache-mynewt-core/apps/bleprph syscfg=BLE_LL_CFG_FEAT_LE_ENCRYPTION=0:BLE_SM_LEGACY=0 Now, let's build the new target: [~/tmp/myproj2]$ newt build split-nrf51dk Building target targets/split-nrf51dk # [...] Target successfully built: targets/split-nrf51dk And look at the size breakdown (again, smaller entries are removed): [~/tmp/myproj2]$ newt size split-nrf51dk Size of Application Image: app FLASH RAM 3064 251 sys_shell.a objsize text data bss dec hex filename 4680 112 17572 22364 575c /home/me/tmp/myproj2/bin/targets/split-nrf51dk/app/apps/splitty/splitty.elf Size of Loader Image: loader FLASH RAM 2446 1533 apps_bleprph.a 1430 104 boot_bootutil.a 1232 0 crypto_mbedtls.a 1107 0 encoding_cborattr.a 2390 0 encoding_tinycbor.a 1764 0 fs_fcb.a 3168 705 hw_drivers_nimble_nrf51.a 4318 109 hw_mcu_nordic_nrf51xxx.a 8285 4049 kernel_os.a 2274 38 libc_baselibc.a 2612 0 libgcc.a 2232 24 mgmt_imgmgr.a 1491 44 mgmt_newtmgr_nmgr_os.a 25169 1946 net_nimble_controller.a 31397 2827 net_nimble_host.a 2259 205 sys_config.a 1318 202 sys_console_full.a 3424 97 sys_log.a 1053 60 sys_stats.a 1296 0 time_datetime.a objsize text data bss dec hex filename 112020 1180 13460 126660 1eec4 /home/me/tmp/myproj2/bin/targets/split-nrf51dk/loader/apps/bleprph/bleprph.elf The size command shows two sets of output: one for the application, and another for the loader. The addition of the split functionality did make bleprph slightly bigger, but notice how small the application is: 4.5 kB! Where before we only had 7 kB left, now we have 105.5 kB. Furthermore, all the functionality in the loader is available to the application at any time. For example, if your application needs bluetooth functionality, it can use the BLE stack present in the loader instead of containing its own copy. Finally, let's deploy the split image to our nRF51dk board. The procedure here is the same as if we were using the Unified setup, i.e., via either the newt load or newt run command. [~/repos/mynewt/core]$ newt load split-nrf51dk 0 Loading app image into slot 2 Loading loader image into slot 1 Image Management Retrieve Current State (image list) Image management in the split setup is a bit more complicated than in the unified setup. You can determine a device's image management state with the newtmgr image list command. Here is how a device responds to this command after our loader + application combo has been deployed: [~/tmp/myproj2]$ newtmgr -c A600ANJ1 image list Images: slot=0 version: 0.0.0 bootable: true flags: active confirmed hash: 948f118966f7989628f8f3be28840fd23a200fc219bb72acdfe9096f06c4b39b slot=1 version: 0.0.0 bootable: false flags: hash: 78e4d263eeb5af5635705b7cae026cc184f14aa6c6c59c6e80616035cd2efc8f Split status: matching There are several interesting things about this response: Two images: This is expected; we deployed both a loader image and an application image. bootable flag: Notice slot 0's bootable flag is set, while slot 1's is not. This tells us that slot 0 contains a loader and slot 1 contains an application. If an image is bootable, it can be booted directly from the boot loader. Non-bootable images can only be started from a loader image. flags: Slot 0 is active and confirmed ; none of slot 1's flags are set. The active flag indicates that the image is currently running; the confirmed flag indicates that the image will continue to be used on subsequent reboots. Slot 1's lack of enabled flags indicates that the image is not being used at all. Split status: The split status field tells you if the loader and application are compatible. A loader + application combo is compatible only if both images were built at the same time with newt . If the loader and application are not compatible, the loader will not boot into the application. Enabling a Split Application By default, the application image in slot 1 is disabled. This is indicated in the image list response above. When you deploy a loader / application combo to your device, the application image won't actually run. Instead, the loader will act as though an application image is not present and remain in \"loader mode\". Typically, a device in loader mode simply acts as an image management server, listening for an image upgrade or a request to activate the application image. Use the following command sequence to enable the split application image: Tell device to \"test out\" the application image on next boot ( newtmgr image test <application-image-hash> ). Reboot device ( newtmgr reset ). Make above change permanent ( newtmgr image confirm ). After the above sequence, a newtmgr image list command elicits the following response: [~/tmp/myproj2]$ newtmgr -c A600ANJ1 image confirm Images: slot=0 version: 0.0.0 bootable: true flags: active confirmed hash: 948f118966f7989628f8f3be28840fd23a200fc219bb72acdfe9096f06c4b39b slot=1 version: 0.0.0 bootable: false flags: active confirmed hash: 78e4d263eeb5af5635705b7cae026cc184f14aa6c6c59c6e80616035cd2efc8f Split status: matching The active confirmed flags value on both slots indicates that both images are permanently running. Image Upgrade First, let's review of the image upgrade process for the Unified setup. The user upgrades to a new image in this setup with the following steps: Image Upgrade - Unified Upload new image to slot 1 ( newtmgr image upload <filename> ). Tell device to \"test out\" the new image on next boot ( newtmgr image test <image-hash> ). Reboot device ( newtmgr reset ). Make new image permanent ( newtmgr image confirm ). Image Upgrade - Split The image upgrade process is a bit more complicated in the Split setup. It is more complicated because two images need to be upgraded (loader and application) rather than just one. The split upgrade process is described below: Disable split functionality; we need to deactivate the application image in slot 1 ( newtmgr image test <current-loader-hash> ). Reboot device ( newtmgr reset ). Make above change permanent ( newtmgr image confirm ). Upload new loader to slot 1 ( newtmgr image upload <filename> ). Tell device to \"test out\" the new loader on next boot ( newtmgr image test <new-loader-hash> ). Reboot device ( newtmgr reset ). Make above change of loader permanent ( newtmgr image confirm ). Upload new application to slot 1 ( newtmgr image upload <filename> ). Tell device to \"test out\" the new application on next boot ( newtmgr image test <new-application-hash> ). Reboot device ( newtmgr reset ). Make above change of application permanent ( newtmgr image confirm ). When performing this process manually, it may be helpful to use image list to check the image management state as you go. Syscfg Syscfg is Mynewt's system-wide configuration mechanism. In a split setup, there is a single umbrella syscfg configuration that applies to both the loader and the application. Consequently, overriding a value in an application-only package potentially affects the loader (and vice-versa). Loaders The following applications have been enabled as loaders. You may choose to build your own loader application, and these can serve as samples. @apache-mynewt-core/apps/slinky @apache-mynewt-core/apps/bleprph Split Apps The following applications have been enabled as split applications. If you choose to build your own split application these can serve as samples. Note that slinky can be either a loader image or an application image. @apache-mynewt-core/apps/slinky @apache-mynewt-core/apps/splitty Theory of Operation A split image is built as follows: First newt builds the application and loader images separately to ensure they are consistent (no errors) and to generate elf files which can inform newt of the symbols used by each part. Then newt collects the symbols used by both application and loader in two ways. It collects the set of symbols from the .elf files. It also collects all the possible symbols from the .a files for each application. Newt builds the set of packages that the two applications share. It ensures that all the symbols used in those packages are matching. NOTE: because of features and #ifdefs, its possible for the two package to have symbols that are not the same. In this case newt generates an error and will not build a split image. Then newt creates the list of symbols that the two applications share from those packages (using the .elf files). Newt re-links the loader to ensure all of these symbols are present in the loader application (by forcing the linker to include them in the .elf ). Newt builds a special copy of the loader.elf with only these symbols (and the handful of symbols discussed in the linking section above). Finally, newt links the application, replacing the common .a libraries with the special loader.elf image during the link.","title":"toc"},{"location":"os/modules/split/split/#split-images","text":"","title":"Split Images"},{"location":"os/modules/split/split/#description","text":"The split image mechanism divides a target into two separate images: one capable of image upgrade; the other containing application code. By isolating upgrade functionality to a separate image, the application can support over-the-air upgrade without dedicating flash space to network stack and management code.","title":"Description"},{"location":"os/modules/split/split/#concept","text":"Mynewt supports three image setups: Setup Description Single One large image; upgrade not supported. Unified Two standalone images. Split Kernel in slot 0; application in slot 1. Each setup has its tradeoffs. The Single setup gives you the most flash space, but doesn't allow you to upgrade after manufacturing. The Unified setup allows for a complete failover in case a bad image gets uploaded, but requires a lot of redundancy in each image, limiting the amount of flash available to the application. The Split setup sits somewhere between these two options. Before exploring the split setup in more detail, it might be helpful to get a basic understanding of the Mynewt boot sequence. The boot process is summarized below.","title":"Concept"},{"location":"os/modules/split/split/#boot-sequence-single","text":"In the Single setup, there is no boot loader. Instead, the image is placed at address 0. The hardware boots directly into the image code. Upgrade is not possible because there is no boot loader to move an alternate image into place.","title":"Boot Sequence - Single"},{"location":"os/modules/split/split/#boot-sequence-unified","text":"In the Unified setup, the boot loader is placed at address 0. At startup, the boot loader arranges for the correct image to be in image slot 0, which may entail swapping the contents of the two image slots. Finally, the boot loader jumps to the image in slot 0.","title":"Boot Sequence - Unified"},{"location":"os/modules/split/split/#boot-sequence-split","text":"The Split setup differs from the other setups mainly in that a target is not fully contained in a single image. Rather, the target is partitioned among two separate images: the loader , and the application . Functionality is divided among these two images as follows: Loader: Mynewt OS. Network stack for connectivity during upgrade e.g. BLE stack. Anything else required for image upgrade. Application: Parts of Mynewt not required for image upgrade. Application-specific code. The loader image serves three purposes: Second-stage boot loader: it jumps into the application image at start up. Image upgrade server: the user can upgrade to a new loader + application combo, even if an application image is not currently running. Functionality container: the application image can directly access all the code present in the loader image From the perspective of the boot loader, a loader image is identical to a plain unified image. What makes a loader image different is a change to its start up sequence: rather than starting the Mynewt OS, it jumps to the application image in slot 1 if one is present.","title":"Boot Sequence - Split"},{"location":"os/modules/split/split/#tutorial","text":"","title":"Tutorial"},{"location":"os/modules/split/split/#building-a-split-image","text":"We will be referring to the nRF51dk for examples in this document. Let's take a look at this board's flash map (defined in hw/bsp/nrf51dk/bsp.yml ): Name Offset Size (kB) Boot loader 0x00000000 16 Reboot log 0x00004000 16 Image slot 0 0x00008000 110 Image slot 1 0x00023800 110 Image scratch 0x0003f000 2 Flash file system 0x0003f800 2 The application we will be building is bleprph . First, we create a target to tie our BSP and application together. newt target create bleprph-nrf51dk newt target set bleprph-nrf51dk \\ app=@apache-mynewt-core/apps/bleprph \\ bsp=@apache-mynewt-core/hw/bsp/nrf51dk \\ build_profile=optimized \\ syscfg=BLE_LL_CFG_FEAT_LE_ENCRYPTION=0:BLE_SM_LEGACY=0 The two syscfg settings disable bluetooth security and keep the code size down. We can verify the target using the target show command: [~/tmp/myproj2]$ newt target show bleprph-nrf51dk targets/bleprph-nrf51dk app=@apache-mynewt-core/apps/bleprph bsp=@apache-mynewt-core/hw/bsp/nrf51dk build_profile=optimized syscfg=BLE_LL_CFG_FEAT_LE_ENCRYPTION=0:BLE_SM_LEGACY=0 Next, build the target: [~/tmp/myproj2]$ newt build bleprph-nrf51dk Building target targets/bleprph-nrf51dk # [...] Target successfully built: targets/bleprph-nrf51dk With our target built, we can view a code size breakdown using the newt size <target> command. In the interest of brevity, the smaller entries are excluded from the below output: [~/tmp/myproj2]$ newt size bleprph-nrf51dk Size of Application Image: app FLASH RAM 2446 1533 apps_bleprph.a 1430 104 boot_bootutil.a 1232 0 crypto_mbedtls.a 1107 0 encoding_cborattr.a 2390 0 encoding_tinycbor.a 1764 0 fs_fcb.a 2959 697 hw_drivers_nimble_nrf51.a 4126 108 hw_mcu_nordic_nrf51xxx.a 8161 4049 kernel_os.a 2254 38 libc_baselibc.a 2612 0 libgcc.a 2232 24 mgmt_imgmgr.a 1499 44 mgmt_newtmgr_nmgr_os.a 23918 1930 net_nimble_controller.a 28537 2779 net_nimble_host.a 2207 205 sys_config.a 1074 197 sys_console_full.a 3268 97 sys_log.a 1296 0 time_datetime.a objsize text data bss dec hex filename 105592 1176 13392 120160 1d560 /home/me/tmp/myproj2/bin/targets/bleprph-nrf51dk/app/apps/bleprph/bleprph.elf The full image text size is about 103kB (where 1kB = 1024 bytes). With an image slot size of 110kB, this leaves only about 7kB of flash for additional application code and data. Not good. This is the situation we would be facing if we were using the Unified setup. The Split setup can go a long way in solving our problem. Our unified bleprph image consists mostly of components that get used during an image upgrade. By using the Split setup, we turn the unified image into two separate images: the loader and the application. The functionality related to image upgrade can be delegated to the loader image, freeing up a significant amount of flash in the application image slot. Let's create a new target to use with the Split setup. We designate a target as a split target by setting the loader variable. In our example, we are going to use bleprph as the loader, and splitty as the application. bleprph makes sense as a loader because it contains the BLE stack and everything else required for an image upgrade. newt target create split-nrf51dk newt target set split-nrf51dk \\ loader=@apache-mynewt-core/apps/bleprph \\ app=@apache-mynewt-core/apps/splitty \\ bsp=@apache-mynewt-core/hw/bsp/nrf51dk \\ build_profile=optimized \\ syscfg=BLE_LL_CFG_FEAT_LE_ENCRYPTION=0:BLE_SM_LEGACY=0 Verify that the target looks correct: [~/tmp/myproj2]$ newt target show split-nrf51dk targets/split-nrf51dk app=@apache-mynewt-core/apps/splitty bsp=@apache-mynewt-core/hw/bsp/nrf51dk build_profile=optimized loader=@apache-mynewt-core/apps/bleprph syscfg=BLE_LL_CFG_FEAT_LE_ENCRYPTION=0:BLE_SM_LEGACY=0 Now, let's build the new target: [~/tmp/myproj2]$ newt build split-nrf51dk Building target targets/split-nrf51dk # [...] Target successfully built: targets/split-nrf51dk And look at the size breakdown (again, smaller entries are removed): [~/tmp/myproj2]$ newt size split-nrf51dk Size of Application Image: app FLASH RAM 3064 251 sys_shell.a objsize text data bss dec hex filename 4680 112 17572 22364 575c /home/me/tmp/myproj2/bin/targets/split-nrf51dk/app/apps/splitty/splitty.elf Size of Loader Image: loader FLASH RAM 2446 1533 apps_bleprph.a 1430 104 boot_bootutil.a 1232 0 crypto_mbedtls.a 1107 0 encoding_cborattr.a 2390 0 encoding_tinycbor.a 1764 0 fs_fcb.a 3168 705 hw_drivers_nimble_nrf51.a 4318 109 hw_mcu_nordic_nrf51xxx.a 8285 4049 kernel_os.a 2274 38 libc_baselibc.a 2612 0 libgcc.a 2232 24 mgmt_imgmgr.a 1491 44 mgmt_newtmgr_nmgr_os.a 25169 1946 net_nimble_controller.a 31397 2827 net_nimble_host.a 2259 205 sys_config.a 1318 202 sys_console_full.a 3424 97 sys_log.a 1053 60 sys_stats.a 1296 0 time_datetime.a objsize text data bss dec hex filename 112020 1180 13460 126660 1eec4 /home/me/tmp/myproj2/bin/targets/split-nrf51dk/loader/apps/bleprph/bleprph.elf The size command shows two sets of output: one for the application, and another for the loader. The addition of the split functionality did make bleprph slightly bigger, but notice how small the application is: 4.5 kB! Where before we only had 7 kB left, now we have 105.5 kB. Furthermore, all the functionality in the loader is available to the application at any time. For example, if your application needs bluetooth functionality, it can use the BLE stack present in the loader instead of containing its own copy. Finally, let's deploy the split image to our nRF51dk board. The procedure here is the same as if we were using the Unified setup, i.e., via either the newt load or newt run command. [~/repos/mynewt/core]$ newt load split-nrf51dk 0 Loading app image into slot 2 Loading loader image into slot 1","title":"Building a Split Image"},{"location":"os/modules/split/split/#image-management","text":"","title":"Image Management"},{"location":"os/modules/split/split/#retrieve-current-state-image-list","text":"Image management in the split setup is a bit more complicated than in the unified setup. You can determine a device's image management state with the newtmgr image list command. Here is how a device responds to this command after our loader + application combo has been deployed: [~/tmp/myproj2]$ newtmgr -c A600ANJ1 image list Images: slot=0 version: 0.0.0 bootable: true flags: active confirmed hash: 948f118966f7989628f8f3be28840fd23a200fc219bb72acdfe9096f06c4b39b slot=1 version: 0.0.0 bootable: false flags: hash: 78e4d263eeb5af5635705b7cae026cc184f14aa6c6c59c6e80616035cd2efc8f Split status: matching There are several interesting things about this response: Two images: This is expected; we deployed both a loader image and an application image. bootable flag: Notice slot 0's bootable flag is set, while slot 1's is not. This tells us that slot 0 contains a loader and slot 1 contains an application. If an image is bootable, it can be booted directly from the boot loader. Non-bootable images can only be started from a loader image. flags: Slot 0 is active and confirmed ; none of slot 1's flags are set. The active flag indicates that the image is currently running; the confirmed flag indicates that the image will continue to be used on subsequent reboots. Slot 1's lack of enabled flags indicates that the image is not being used at all. Split status: The split status field tells you if the loader and application are compatible. A loader + application combo is compatible only if both images were built at the same time with newt . If the loader and application are not compatible, the loader will not boot into the application.","title":"Retrieve Current State (image list)"},{"location":"os/modules/split/split/#enabling-a-split-application","text":"By default, the application image in slot 1 is disabled. This is indicated in the image list response above. When you deploy a loader / application combo to your device, the application image won't actually run. Instead, the loader will act as though an application image is not present and remain in \"loader mode\". Typically, a device in loader mode simply acts as an image management server, listening for an image upgrade or a request to activate the application image. Use the following command sequence to enable the split application image: Tell device to \"test out\" the application image on next boot ( newtmgr image test <application-image-hash> ). Reboot device ( newtmgr reset ). Make above change permanent ( newtmgr image confirm ). After the above sequence, a newtmgr image list command elicits the following response: [~/tmp/myproj2]$ newtmgr -c A600ANJ1 image confirm Images: slot=0 version: 0.0.0 bootable: true flags: active confirmed hash: 948f118966f7989628f8f3be28840fd23a200fc219bb72acdfe9096f06c4b39b slot=1 version: 0.0.0 bootable: false flags: active confirmed hash: 78e4d263eeb5af5635705b7cae026cc184f14aa6c6c59c6e80616035cd2efc8f Split status: matching The active confirmed flags value on both slots indicates that both images are permanently running.","title":"Enabling a Split Application"},{"location":"os/modules/split/split/#image-upgrade","text":"First, let's review of the image upgrade process for the Unified setup. The user upgrades to a new image in this setup with the following steps:","title":"Image Upgrade"},{"location":"os/modules/split/split/#image-upgrade-unified","text":"Upload new image to slot 1 ( newtmgr image upload <filename> ). Tell device to \"test out\" the new image on next boot ( newtmgr image test <image-hash> ). Reboot device ( newtmgr reset ). Make new image permanent ( newtmgr image confirm ).","title":"Image Upgrade - Unified"},{"location":"os/modules/split/split/#image-upgrade-split","text":"The image upgrade process is a bit more complicated in the Split setup. It is more complicated because two images need to be upgraded (loader and application) rather than just one. The split upgrade process is described below: Disable split functionality; we need to deactivate the application image in slot 1 ( newtmgr image test <current-loader-hash> ). Reboot device ( newtmgr reset ). Make above change permanent ( newtmgr image confirm ). Upload new loader to slot 1 ( newtmgr image upload <filename> ). Tell device to \"test out\" the new loader on next boot ( newtmgr image test <new-loader-hash> ). Reboot device ( newtmgr reset ). Make above change of loader permanent ( newtmgr image confirm ). Upload new application to slot 1 ( newtmgr image upload <filename> ). Tell device to \"test out\" the new application on next boot ( newtmgr image test <new-application-hash> ). Reboot device ( newtmgr reset ). Make above change of application permanent ( newtmgr image confirm ). When performing this process manually, it may be helpful to use image list to check the image management state as you go.","title":"Image Upgrade - Split"},{"location":"os/modules/split/split/#syscfg","text":"Syscfg is Mynewt's system-wide configuration mechanism. In a split setup, there is a single umbrella syscfg configuration that applies to both the loader and the application. Consequently, overriding a value in an application-only package potentially affects the loader (and vice-versa).","title":"Syscfg"},{"location":"os/modules/split/split/#loaders","text":"The following applications have been enabled as loaders. You may choose to build your own loader application, and these can serve as samples. @apache-mynewt-core/apps/slinky @apache-mynewt-core/apps/bleprph","title":"Loaders"},{"location":"os/modules/split/split/#split-apps","text":"The following applications have been enabled as split applications. If you choose to build your own split application these can serve as samples. Note that slinky can be either a loader image or an application image. @apache-mynewt-core/apps/slinky @apache-mynewt-core/apps/splitty","title":"Split Apps"},{"location":"os/modules/split/split/#theory-of-operation","text":"A split image is built as follows: First newt builds the application and loader images separately to ensure they are consistent (no errors) and to generate elf files which can inform newt of the symbols used by each part. Then newt collects the symbols used by both application and loader in two ways. It collects the set of symbols from the .elf files. It also collects all the possible symbols from the .a files for each application. Newt builds the set of packages that the two applications share. It ensures that all the symbols used in those packages are matching. NOTE: because of features and #ifdefs, its possible for the two package to have symbols that are not the same. In this case newt generates an error and will not build a split image. Then newt creates the list of symbols that the two applications share from those packages (using the .elf files). Newt re-links the loader to ensure all of these symbols are present in the loader application (by forcing the linker to include them in the .elf ). Newt builds a special copy of the loader.elf with only these symbols (and the handful of symbols discussed in the linking section above). Finally, newt links the application, replacing the common .a libraries with the special loader.elf image during the link.","title":"Theory of Operation"},{"location":"os/modules/stats/stats/","text":"Statistics Module The statistics module allows application, libraries, or drivers to record statistics that can be shown via the Newtmgr tool and console. This allows easy integration of statistics for troubleshooting, maintenance, and usage monitoring. By creating and registering your statistics, they are automatically included in the Newtmgr shell and console APIs. Implementation Details A statistic is an unsigned integer that can be set by the code. When building stats, the implementer chooses the size of the statistic depending on the frequency of the statistic and the resolution required before the counter wraps. Typically the stats are incremented upon code events; however, they are not limted to that purpose. Stats are organized into sections. Each section of stats has its own name and can be queried separately through the API. Each section of stats also has its own statistic size, allowing the user to separate large (64-bit) statistics from small (16 bit statistics). NOTE: It is not currently possible to group different size stats into the same section. Please ensure all stats in a section have the same size. Stats sections are currently stored in a single global stats group. Statistics are stored in a simple structure which contains a small stats header followed by a list of stats. The stats header contains: struct stats_hdr { char *s_name ; uint8_t s_size ; uint8_t s_cnt ; uint16_t s_pad1 ; #ifdef STATS_NAME_ENABLE struct stats_name_map *s_map ; int s_map_cnt ; #endif STAILQ_ENTRY ( stats_hdr ) s_next ; }; Compile Time Options When building your app, there is a single compile time option for statistics. When querying statistics, they are always queried by number, but if you want to see the results by name, you need to define STATS_NAME_ENABLE . This is defined using pkg.clfags: -DSTATS_NAME_ENABLE in your apps pkg.yml file or target.clfags: -DSTATS_NAME_ENABLE in your target definition. Enabling stat names provides better descriptions in the reported stats, but takes code space to store the strings within the image. Adding Stats to your code. Creating new stats table requires the following steps. Include the stats header file Define a stats section Declare an instance of the section Define the stat sections names table Implement stat in your code Initialize the stats Register the stats Include the stats header file Add the stats library to your pkg.yml file for your package or app by adding this line to your package dependencies. pkg.deps: - \"@apache-mynewt-core/sys/stats\" Add this include directive to code files using the stats library. #include <stats/stats.h> Define a stats section You must use the stats.h macros to define your stats table. A stats section definition looks like this. STATS_SECT_START(my_stat_section) STATS_SECT_ENTRY(attempt_stat) STATS_SECT_ENTRY(error_stat) STATS_SECT_END In this case we chose to make the stats 32-bits each. stats.h supports three different stats sizes through the following macros: STATS_SIZE_16 -- stats are 16 bits (wraps at 65536) STATS_SIZE_32 -- stats are 32 bits (wraps at 4294967296) STATS_SIZE_64 -- stats are 64-bits When this compiles/pre-processes, it produces a structure definition like this struct stats_my_stat_section { struct stats_hdr s_hdr; uint32_t sattempt_stat; uint32_t serror_stat; }; You can see that the defined structure has a small stats structure header and the two stats we have defined. Depending on whether these stats are used in multiple modules, you may need to include this definition in a header file. Declaring a variable to hold the stats Declare the global variable to hold your statistics. Since it is possible to have multiple copies of the same section (for example a stat section for each of 5 identical peripherals), the variable name of the stats section must be unique. STATS_SECT_DECL(my_stat_section) g_mystat; Again, if your stats section is used in multiple C files you will need to include the above definition in one of the C files and 'extern' this declaration in your header file. extern STATS_SECT_DECL(my_stat_section) g_mystat; Define the stats section name table Whether or not you are using STATS_NAME_ENABLE , you must define a stats name table. If STATS_NAME_ENABLE is not enabled, this will not take any code space or image size. /* define a few stats for querying */ STATS_NAME_START(my_stat_section) STATS_NAME(my_stat_section, attempt_stat) STATS_NAME(my_stat_section, error_stat) STATS_NAME_END(my_stat_section) When compiled by the preprocessor, it creates a structure that looks like this. struct stats_name_map g_stats_map_my_stat_section[] = { { __builtin_offsetof (struct stats_my_stat_section, sattempt_stat), \"attempt_stat\" }, { __builtin_offsetof (struct stats_my_stat_section, serror_stat), \"error_stat\" }, }; This table will allow the UI components to find a nice string name for the stat. Implement stats in your code. You can use the STATS_INC or STATS_INCN macros to increment your statistics within your C-code. For example, your code may do this: STATS_INC(g_mystat, attempt_stat); rc = do_task(); if(rc == ERR) { STATS_INC(g_mystat, error_stat); } Initialize the statistics You must initialize the stats so they can be operated on by the stats library. As per our example above, it would look like the following. This tells the system how large each statistic is and the number of statistics in the section. It also initialize the name information for the statistics if enabled as shown above. rc = stats_init( STATS_HDR(g_mystat), STATS_SIZE_INIT_PARMS(g_mystat, STATS_SIZE_32), STATS_NAME_INIT_PARMS(my_stat_section)); assert(rc == 0); Register the statistic section If you want the system to know about your stats, you must register them. rc = stats_register(\"my_stats\", STATS_HDR(g_mystat)); assert(rc == 0); There is also a method that does initialization and registration at the same time, called stats_init_and_reg . Retrieving stats through console or Newtmgr If you enable console in your project you can see stats through the serial port defined. This is the stats as shown from the example above with names enabled. stat my_stats 12274:attempt_stat: 3 12275:error_stat: 0 This is the stats as shown from the example without names enabled. stat my_stats 29149:s0: 3 29150:s1: 0 A note on multiple stats sections If you are implementing a device with multiple instances, you may want multiple stats sections with the exact same format. For example, suppose I write a driver for an external distance sensor. My driver supports up to 5 sensors and I want to record the stats of each device separately. This works identically to the example above, except you would need to register each one separately with a unique name. The stats system will not let two sections be entered with the same name.","title":"toc"},{"location":"os/modules/stats/stats/#statistics-module","text":"The statistics module allows application, libraries, or drivers to record statistics that can be shown via the Newtmgr tool and console. This allows easy integration of statistics for troubleshooting, maintenance, and usage monitoring. By creating and registering your statistics, they are automatically included in the Newtmgr shell and console APIs.","title":"Statistics Module"},{"location":"os/modules/stats/stats/#implementation-details","text":"A statistic is an unsigned integer that can be set by the code. When building stats, the implementer chooses the size of the statistic depending on the frequency of the statistic and the resolution required before the counter wraps. Typically the stats are incremented upon code events; however, they are not limted to that purpose. Stats are organized into sections. Each section of stats has its own name and can be queried separately through the API. Each section of stats also has its own statistic size, allowing the user to separate large (64-bit) statistics from small (16 bit statistics). NOTE: It is not currently possible to group different size stats into the same section. Please ensure all stats in a section have the same size. Stats sections are currently stored in a single global stats group. Statistics are stored in a simple structure which contains a small stats header followed by a list of stats. The stats header contains: struct stats_hdr { char *s_name ; uint8_t s_size ; uint8_t s_cnt ; uint16_t s_pad1 ; #ifdef STATS_NAME_ENABLE struct stats_name_map *s_map ; int s_map_cnt ; #endif STAILQ_ENTRY ( stats_hdr ) s_next ; };","title":"Implementation Details"},{"location":"os/modules/stats/stats/#compile-time-options","text":"When building your app, there is a single compile time option for statistics. When querying statistics, they are always queried by number, but if you want to see the results by name, you need to define STATS_NAME_ENABLE . This is defined using pkg.clfags: -DSTATS_NAME_ENABLE in your apps pkg.yml file or target.clfags: -DSTATS_NAME_ENABLE in your target definition. Enabling stat names provides better descriptions in the reported stats, but takes code space to store the strings within the image.","title":"Compile Time Options"},{"location":"os/modules/stats/stats/#adding-stats-to-your-code","text":"Creating new stats table requires the following steps. Include the stats header file Define a stats section Declare an instance of the section Define the stat sections names table Implement stat in your code Initialize the stats Register the stats","title":"Adding Stats to your code."},{"location":"os/modules/stats/stats/#include-the-stats-header-file","text":"Add the stats library to your pkg.yml file for your package or app by adding this line to your package dependencies. pkg.deps: - \"@apache-mynewt-core/sys/stats\" Add this include directive to code files using the stats library. #include <stats/stats.h>","title":"Include the stats header file"},{"location":"os/modules/stats/stats/#define-a-stats-section","text":"You must use the stats.h macros to define your stats table. A stats section definition looks like this. STATS_SECT_START(my_stat_section) STATS_SECT_ENTRY(attempt_stat) STATS_SECT_ENTRY(error_stat) STATS_SECT_END In this case we chose to make the stats 32-bits each. stats.h supports three different stats sizes through the following macros: STATS_SIZE_16 -- stats are 16 bits (wraps at 65536) STATS_SIZE_32 -- stats are 32 bits (wraps at 4294967296) STATS_SIZE_64 -- stats are 64-bits When this compiles/pre-processes, it produces a structure definition like this struct stats_my_stat_section { struct stats_hdr s_hdr; uint32_t sattempt_stat; uint32_t serror_stat; }; You can see that the defined structure has a small stats structure header and the two stats we have defined. Depending on whether these stats are used in multiple modules, you may need to include this definition in a header file.","title":"Define a stats section"},{"location":"os/modules/stats/stats/#declaring-a-variable-to-hold-the-stats","text":"Declare the global variable to hold your statistics. Since it is possible to have multiple copies of the same section (for example a stat section for each of 5 identical peripherals), the variable name of the stats section must be unique. STATS_SECT_DECL(my_stat_section) g_mystat; Again, if your stats section is used in multiple C files you will need to include the above definition in one of the C files and 'extern' this declaration in your header file. extern STATS_SECT_DECL(my_stat_section) g_mystat;","title":"Declaring a variable to hold the stats"},{"location":"os/modules/stats/stats/#define-the-stats-section-name-table","text":"Whether or not you are using STATS_NAME_ENABLE , you must define a stats name table. If STATS_NAME_ENABLE is not enabled, this will not take any code space or image size. /* define a few stats for querying */ STATS_NAME_START(my_stat_section) STATS_NAME(my_stat_section, attempt_stat) STATS_NAME(my_stat_section, error_stat) STATS_NAME_END(my_stat_section) When compiled by the preprocessor, it creates a structure that looks like this. struct stats_name_map g_stats_map_my_stat_section[] = { { __builtin_offsetof (struct stats_my_stat_section, sattempt_stat), \"attempt_stat\" }, { __builtin_offsetof (struct stats_my_stat_section, serror_stat), \"error_stat\" }, }; This table will allow the UI components to find a nice string name for the stat.","title":"Define the stats section name table"},{"location":"os/modules/stats/stats/#implement-stats-in-your-code","text":"You can use the STATS_INC or STATS_INCN macros to increment your statistics within your C-code. For example, your code may do this: STATS_INC(g_mystat, attempt_stat); rc = do_task(); if(rc == ERR) { STATS_INC(g_mystat, error_stat); }","title":"Implement stats in your code."},{"location":"os/modules/stats/stats/#initialize-the-statistics","text":"You must initialize the stats so they can be operated on by the stats library. As per our example above, it would look like the following. This tells the system how large each statistic is and the number of statistics in the section. It also initialize the name information for the statistics if enabled as shown above. rc = stats_init( STATS_HDR(g_mystat), STATS_SIZE_INIT_PARMS(g_mystat, STATS_SIZE_32), STATS_NAME_INIT_PARMS(my_stat_section)); assert(rc == 0);","title":"Initialize the statistics"},{"location":"os/modules/stats/stats/#register-the-statistic-section","text":"If you want the system to know about your stats, you must register them. rc = stats_register(\"my_stats\", STATS_HDR(g_mystat)); assert(rc == 0); There is also a method that does initialization and registration at the same time, called stats_init_and_reg .","title":"Register the statistic section"},{"location":"os/modules/stats/stats/#retrieving-stats-through-console-or-newtmgr","text":"If you enable console in your project you can see stats through the serial port defined. This is the stats as shown from the example above with names enabled. stat my_stats 12274:attempt_stat: 3 12275:error_stat: 0 This is the stats as shown from the example without names enabled. stat my_stats 29149:s0: 3 29150:s1: 0","title":"Retrieving stats through console or Newtmgr"},{"location":"os/modules/stats/stats/#a-note-on-multiple-stats-sections","text":"If you are implementing a device with multiple instances, you may want multiple stats sections with the exact same format. For example, suppose I write a driver for an external distance sensor. My driver supports up to 5 sensors and I want to record the stats of each device separately. This works identically to the example above, except you would need to register each one separately with a unique name. The stats system will not let two sections be entered with the same name.","title":"A note on multiple stats sections"},{"location":"os/modules/sysinitconfig/sysconfig_error/","text":"Validation and Error Messages With multiple packages defining and overriding system configuration settings, it is easy to introduce conflicts and violations that are difficult to find. The newt build <target-name> command validates the setting definitions and value overrides for all the packages in the target to ensure a valid and consistent build. It aborts the build when it detects violations or ambiguities between packages. The following sections describe the error conditions that newt detects and the error messages that it outputs. For most errors, newt also outputs the Setting history with the order of package overrides to help you resolve the errors. Note: The newt target config <target-name> command also detects errors and outputs error messages at the top of the command output. The command outputs the package setting definitions and values after it outputs the error messages. It is easy to miss the error messages at the top. Value Override Violations The newt tool uses package priorities to resolve override conflicts. It uses the value override from the highest priority package when multiple packages override the same setting. Newt checks for the following override violations: Ambiguity Violation - Two packages of the same priority override a setting with different values. And no higher priority package overrides the setting. Priority Violation - A package overrides a setting defined by a package with higher or equal priority. Example: Ambiguity Violation Error Message The following example shows the error message that newt outputs for an ambiguity violation: Error: Syscfg ambiguities detected: Setting: LOG_NEWTMGR, Packages: [apps/slinky, apps/splitty] Setting history (newest -> oldest): LOG_NEWTMGR: [apps/splitty:0, apps/slinky:1, sys/log/full:0] The above error occurs because the apps/slinky and apps/splitty packages in the split image target both override the same setting with different values. The apps/slinky package sets the sys/log/full package LOG_NEWTMGR setting to 1, and the apps/splitty package sets the setting to 0. The overrides are ambiguous because both are app packages and have the same priority. The following are excerpts of the defintion and the two overrides from the syscfg.yml files that cause the error: #Package: sys/log/full syscfg.defs: LOG_NEWTMGR: description: 'Enables or disables newtmgr command tool logging' value: 0 #Package: apps/slinky syscfg.vals: LOG_NEWTMGR: 1 #Package: apps/splitty syscfg.vals: LOG_NEWTMGR: 0 Example: Priority Violation Error Message The following example shows the error message that newt outputs for a priority violation where a package tries to change the setting that was defined by another package at the same priority level: Error: Priority violations detected (Packages can only override settings defined by packages of lower priority): Package: mgmt/newtmgr overriding setting: LOG_NEWTMGR defined by sys/log/full Setting history (newest -> oldest): LOG_NEWTMGR: [sys/log/full:0] The above error occurs because the mgmt/newtmgr lib package overrides the LOG_NEWTMGR setting that the sys/log/full lib package defines. The following are excerpts of the definition and the override from the syscfg.yml files that cause this error: #Package: sys/log/full syscfg.defs: LOG_NEWTMGR: description: 'Enables or disables newtmgr command tool logging' value: 0 #Package: mgmt/newtmgr syscfg.vals: LOG_NEWTMGR: 1 Flash Area Violations For flash_owner type setting definitions, newt checks for the following violations: An undefined flash area is assigned to a setting. A flash area is assigned to multiple settings. Example: Undefined Flash Area Error Message The following example shows the error message that newt outputs for an undefined flash area. Building target targets/sim_slinky Error: Flash errors detected: Setting REBOOT_LOG_FLASH_AREA specifies unknown flash area: FLASH_AREA_NOEXIST Setting history (newest -> oldest): REBOOT_LOG_FLASH_AREA: [hw/bsp/native:FLASH_AREA_NOEXIST, sys/reboot:] The above error occurs because the hw/bsp/native package assigns the undefined FLASH_AREA_NOEXIST flash area to the sys/reboot package REBOOT_LOG_FLASH_AREA setting. The following are excerpts of the definition and the override from the syscfg.yml files that cause the error: #Package: sys/reboot syscfg.defs: REBOOT_LOG_FLASH_AREA: description: 'Flash Area to use for reboot log.' type: flash_owner value: #Package: hw/bsp/native syscfg.vals: REBOOT_LOG_FLASH_AREA: FLASH_AREA_NOEXIST Example: Multiple Flash Area Assignment Error Message The following example shows the error message that newt outputs when multiple settings are assigned the same flash area: Error: Flash errors detected: Multiple flash_owner settings specify the same flash area settings: REBOOT_LOG_FLASH_AREA, CONFIG_FCB_FLASH_AREA flash area: FLASH_AREA_NFFS Setting history (newest -> oldest): CONFIG_FCB_FLASH_AREA: [hw/bsp/native:FLASH_AREA_NFFS, sys/config:] REBOOT_LOG_FLASH_AREA: [apps/slinky:FLASH_AREA_NFFS, sys/reboot:] The above error occurs because the hw/bsp/native package assigns the FLASH_AREA_NFFS flash area to the sys/config/ package CONFIG_FCB_FLASH_AREA setting, and the apps/slinky package also assigns FLASH_AREA_NFFS to the sys/reboot package REBOOT_LOG_FLASH_AREA setting. The following are excerpts of the two definitions and the two overrides from the syscfg.yml files that cause the error: # Package: sys/config syscfg.defs.CONFIG_FCB: CONFIG_FCB_FLASH_AREA: description: 'The flash area for the Config Flash Circular Buffer' type: 'flash_owner' value: # Package: sys/reboot syscfg.defs: REBOOT_LOG_FLASH_AREA: description: 'The flash area for the reboot log' type: 'flash_owner' value: #Package: hw/bsp/native syscfg.vals: CONFIG_FCB_FLASH_AREA: FLASH_AREA_NFFS #Package: apps/slinky syscfg.vals: REBOOT_LOG_FLASH_AREA: FLASH_AREA_NFFS Restriction Violations For setting definitions with restrictions specified, newt checks for the following violations: A setting with a $notnull restriction does not have a value. For a setting with expression restrictions, some required setting values in the expressions evaluate to false. Example: $notnull Restriction Violation Error Message The following example shows the error message that newt outputs when a setting with $notnull restriction does not have a value: Error: Syscfg restriction violations detected: NFFS_FLASH_AREA must not be null Setting history (newest -> oldest): NFFS_FLASH_AREA: [fs/nffs:] The above error occurs because the fs/nffs package defines the NFFS_FLASH_AREA setting with a $notnull restriction and no packages override the setting. The following is an excerpt of the definition in the syscfg.yml file that causes the error: #Package: fs/nffs syscfg.defs: NFFS_FLASH_AREA: description: 'The flash area to use for the Newtron Flash File System' type: flash_owner value: restrictions: - $notnull Example: Expression Restriction Violation Error Message The following example shows the error message that newt outputs for an expression restriction violation: Error: Syscfg restriction violations detected: CONFIG_FCB=1 requires CONFIG_FCB_FLASH_AREA be set, but CONFIG_FCB_FLASH_AREA= Setting history (newest -> oldest): CONFIG_FCB: [targets/sim_slinky:1, sys/config:0] CONFIG_FCB_FLASH_AREA: [sys/config:] The above error occurs because the sys/config package defines the CONFIG_FCB setting with a restriction that when set, requires that the CONFIG_FCB_FLASH_AREA setting must also be set. The following are excerpts of the definition and the override from the syscfg.yml files that cause the error: # Package: sys/config syscfg.defs: CONFIG_FCB: description: 'Uses Config Flash Circular Buffer' value: 0 restrictions: - '!CONFIG_NFFS' - 'CONFIG_FCB_FLASH_AREA' # Package: targets/sim_slinky syscfg.vals: CONFIG_FCB: 1 Task Priority Violations For task_priority type setting definitions, newt checks for the following violations: A task priority number is assigned to multiple settings. The task priority number is greater than 239. Example: Duplicate Task Priority Assignment Error Message The following example shows the error message that newt outputs when a task priority number is assigned to multiple settings. Note: The settings used in this example are not actual apps/slinky and sys/shell settings. These settings are created for this example because currently only one Mynewt package defines a task_priority type setting. Error: duplicate priority value: setting1=SHELL_TASK_PRIORITY setting2=SLINKY_TASK_PRIORITY pkg1=apps/slinky pkg2=sys/shell value=1 The above error occurs because the apps/slinky package defines a SLINKY_TASK_PRIORITY setting with a default task priority of 1 and the sys/shell package also defines a SHELL_TASK_PRIORITY setting with a default task priority of 1. Example: Invalid Task Priority Error Message The following example shows the error message that newt outputs when a setting is assigned an invalid task priority value: Error: invalid priority value: value too great (> 239); setting=SLINKY_TASK_PRIORITY value=240 pkg=apps/slinky The above error occurs because the apps/slinky package defines the SLINKY_TASK_PRIORITY setting with 240 for the default task priority value. Note: Newt does not output the Setting history with task priority violation error messages. Duplicate System Configuration Setting Definition A setting definition must be unique. Newt checks that only one package in the target defines a setting. The following example shows the error message that newt outputs when multiple packages define the LOG_NEWTMGR setting: Error: setting LOG_NEWTMGR redefined Note: Newt does not output the Setting history with duplicate setting error messages. Override of Undefined System Configuration Setting The newt build command ignores overrides of undefined system configuration settings. The command does not print a warning when you run it with the default log level. If you override a setting and the value is not assigned to the setting, you may have misspelled the setting name or a package no longer defines the setting. You have two options to troubleshoot this problem: Run the newt target config show command to see the configuration setting definitions and overrides. Run the newt build -ldebug command to build your target with DEBUG log level. Note: The newt build -ldebug command generates lots of output and we recommend that you use the newt target config show command option. Example: Ignoring Override of Undefined Setting Message The following example shows that the apps/slinky application overrides the LOG_NEWTMGR setting but omits the T as an example of an error and overrides the misspelled LOG_NEWMGR setting. Here is an excerpt from its syscfg.yml file: #package: apps/slinky syscfg.vals: # Enable the shell task. SHELL_TASK: 1 ... # Enable newtmgr commands. STATS_NEWTMGR: 1 LOG_NEWMGR: 1 The newt target config show slinky_sim command outputs the following WARNING message: 2017/02/18 17:19:12.119 [WARNING] Ignoring override of undefined settings: 2017/02/18 17:19:12.119 [WARNING] LOG_NEWMGR 2017/02/18 17:19:12.119 [WARNING] NFFS_FLASH_AREA 2017/02/18 17:19:12.119 [WARNING] Setting history (newest -> oldest): 2017/02/18 17:19:12.119 [WARNING] LOG_NEWMGR: [apps/slinky:1] 2017/02/18 17:19:12.119 [WARNING] NFFS_FLASH_AREA: [hw/bsp/native:FLASH_AREA_NFFS] The newt build -ldebug slinky_sim command outputs the following DEBUG message: 2017/02/18 17:06:21.451 [DEBUG] Ignoring override of undefined settings: 2017/02/18 17:06:21.451 [DEBUG] LOG_NEWMGR 2017/02/18 17:06:21.451 [DEBUG] NFFS_FLASH_AREA 2017/02/18 17:06:21.451 [DEBUG] Setting history (newest -> oldest): 2017/02/18 17:06:21.451 [DEBUG] LOG_NEWMGR: [apps/slinky:1] 2017/02/18 17:06:21.451 [DEBUG] NFFS_FLASH_AREA: [hw/bsp/native:FLASH_AREA_NFFS] BSP Package Overrides Undefined Configuration Settings You might see a warning that indicates your application's BSP package is overriding some undefined settings. As you can see from the previous example, the WARNING message shows that the hw/bsp/native package is overriding the undefined NFFS_FLASH_AREA setting. This is not an error because of the way a BSP package defines and assigns its flash areas to packages that use flash memory. A BSP package defines, in its bsp.yml file, a flash area map of the flash areas on the board. A package that uses flash memory must define a flash area configuration setting name. The BSP package overrides the package's flash area setting with one of the flash areas from its flash area map. A BSP package overrides the flash area settings for all packages that use flash memory because it does not know the packages that an application uses. When an application does not include one of these packages, the flash area setting for the package is undefined. You will see a message that indicates the BSP package overrides this undefined setting. Here are excerpts from the hw/bsp/native package's bsp.yml and syscfg.yml files for the slinky_sim target. The BSP package defines the flash area map in its bsp.yml file and overrides the flash area settings for all packages in its syscfg.yml file. The slinky_sim target does not use the fs/nffs package which defines the NFFS_FLASH_AREA setting. Newt warns that the hw/bsp/native packages overrides the undefined NFFS_FLASH_AREA setting. # hw/bsp/native bsp.yml bsp.flash_map: areas: # System areas. FLASH_AREA_BOOTLOADER: device: 0 offset: 0x00000000 size: 16kB ... FLASH_AREA_IMAGE_SCRATCH: device: 0 offset: 0x000e0000 size: 128kB # User areas. FLASH_AREA_REBOOT_LOG: user_id: 0 device: 0 offset: 0x00004000 size: 16kB FLASH_AREA_NFFS: user_id: 1 device: 0 offset: 0x00008000 # hw/bsp/native syscfg.yml syscfg.vals: NFFS_FLASH_AREA: FLASH_AREA_NFFS CONFIG_FCB_FLASH_AREA: FLASH_AREA_NFFS REBOOT_LOG_FLASH_AREA: FLASH_AREA_REBOOT_LOG","title":"Validation and Error Messages"},{"location":"os/modules/sysinitconfig/sysconfig_error/#validation-and-error-messages","text":"With multiple packages defining and overriding system configuration settings, it is easy to introduce conflicts and violations that are difficult to find. The newt build <target-name> command validates the setting definitions and value overrides for all the packages in the target to ensure a valid and consistent build. It aborts the build when it detects violations or ambiguities between packages. The following sections describe the error conditions that newt detects and the error messages that it outputs. For most errors, newt also outputs the Setting history with the order of package overrides to help you resolve the errors. Note: The newt target config <target-name> command also detects errors and outputs error messages at the top of the command output. The command outputs the package setting definitions and values after it outputs the error messages. It is easy to miss the error messages at the top.","title":"Validation and Error Messages"},{"location":"os/modules/sysinitconfig/sysconfig_error/#value-override-violations","text":"The newt tool uses package priorities to resolve override conflicts. It uses the value override from the highest priority package when multiple packages override the same setting. Newt checks for the following override violations: Ambiguity Violation - Two packages of the same priority override a setting with different values. And no higher priority package overrides the setting. Priority Violation - A package overrides a setting defined by a package with higher or equal priority.","title":"Value Override Violations"},{"location":"os/modules/sysinitconfig/sysconfig_error/#example-ambiguity-violation-error-message","text":"The following example shows the error message that newt outputs for an ambiguity violation: Error: Syscfg ambiguities detected: Setting: LOG_NEWTMGR, Packages: [apps/slinky, apps/splitty] Setting history (newest -> oldest): LOG_NEWTMGR: [apps/splitty:0, apps/slinky:1, sys/log/full:0] The above error occurs because the apps/slinky and apps/splitty packages in the split image target both override the same setting with different values. The apps/slinky package sets the sys/log/full package LOG_NEWTMGR setting to 1, and the apps/splitty package sets the setting to 0. The overrides are ambiguous because both are app packages and have the same priority. The following are excerpts of the defintion and the two overrides from the syscfg.yml files that cause the error: #Package: sys/log/full syscfg.defs: LOG_NEWTMGR: description: 'Enables or disables newtmgr command tool logging' value: 0 #Package: apps/slinky syscfg.vals: LOG_NEWTMGR: 1 #Package: apps/splitty syscfg.vals: LOG_NEWTMGR: 0","title":"Example: Ambiguity Violation Error Message"},{"location":"os/modules/sysinitconfig/sysconfig_error/#example-priority-violation-error-message","text":"The following example shows the error message that newt outputs for a priority violation where a package tries to change the setting that was defined by another package at the same priority level: Error: Priority violations detected (Packages can only override settings defined by packages of lower priority): Package: mgmt/newtmgr overriding setting: LOG_NEWTMGR defined by sys/log/full Setting history (newest -> oldest): LOG_NEWTMGR: [sys/log/full:0] The above error occurs because the mgmt/newtmgr lib package overrides the LOG_NEWTMGR setting that the sys/log/full lib package defines. The following are excerpts of the definition and the override from the syscfg.yml files that cause this error: #Package: sys/log/full syscfg.defs: LOG_NEWTMGR: description: 'Enables or disables newtmgr command tool logging' value: 0 #Package: mgmt/newtmgr syscfg.vals: LOG_NEWTMGR: 1","title":"Example: Priority Violation Error Message"},{"location":"os/modules/sysinitconfig/sysconfig_error/#flash-area-violations","text":"For flash_owner type setting definitions, newt checks for the following violations: An undefined flash area is assigned to a setting. A flash area is assigned to multiple settings.","title":"Flash Area Violations"},{"location":"os/modules/sysinitconfig/sysconfig_error/#example-undefined-flash-area-error-message","text":"The following example shows the error message that newt outputs for an undefined flash area. Building target targets/sim_slinky Error: Flash errors detected: Setting REBOOT_LOG_FLASH_AREA specifies unknown flash area: FLASH_AREA_NOEXIST Setting history (newest -> oldest): REBOOT_LOG_FLASH_AREA: [hw/bsp/native:FLASH_AREA_NOEXIST, sys/reboot:] The above error occurs because the hw/bsp/native package assigns the undefined FLASH_AREA_NOEXIST flash area to the sys/reboot package REBOOT_LOG_FLASH_AREA setting. The following are excerpts of the definition and the override from the syscfg.yml files that cause the error: #Package: sys/reboot syscfg.defs: REBOOT_LOG_FLASH_AREA: description: 'Flash Area to use for reboot log.' type: flash_owner value: #Package: hw/bsp/native syscfg.vals: REBOOT_LOG_FLASH_AREA: FLASH_AREA_NOEXIST","title":"Example: Undefined Flash Area Error Message"},{"location":"os/modules/sysinitconfig/sysconfig_error/#example-multiple-flash-area-assignment-error-message","text":"The following example shows the error message that newt outputs when multiple settings are assigned the same flash area: Error: Flash errors detected: Multiple flash_owner settings specify the same flash area settings: REBOOT_LOG_FLASH_AREA, CONFIG_FCB_FLASH_AREA flash area: FLASH_AREA_NFFS Setting history (newest -> oldest): CONFIG_FCB_FLASH_AREA: [hw/bsp/native:FLASH_AREA_NFFS, sys/config:] REBOOT_LOG_FLASH_AREA: [apps/slinky:FLASH_AREA_NFFS, sys/reboot:] The above error occurs because the hw/bsp/native package assigns the FLASH_AREA_NFFS flash area to the sys/config/ package CONFIG_FCB_FLASH_AREA setting, and the apps/slinky package also assigns FLASH_AREA_NFFS to the sys/reboot package REBOOT_LOG_FLASH_AREA setting. The following are excerpts of the two definitions and the two overrides from the syscfg.yml files that cause the error: # Package: sys/config syscfg.defs.CONFIG_FCB: CONFIG_FCB_FLASH_AREA: description: 'The flash area for the Config Flash Circular Buffer' type: 'flash_owner' value: # Package: sys/reboot syscfg.defs: REBOOT_LOG_FLASH_AREA: description: 'The flash area for the reboot log' type: 'flash_owner' value: #Package: hw/bsp/native syscfg.vals: CONFIG_FCB_FLASH_AREA: FLASH_AREA_NFFS #Package: apps/slinky syscfg.vals: REBOOT_LOG_FLASH_AREA: FLASH_AREA_NFFS","title":"Example: Multiple Flash Area Assignment Error Message"},{"location":"os/modules/sysinitconfig/sysconfig_error/#restriction-violations","text":"For setting definitions with restrictions specified, newt checks for the following violations: A setting with a $notnull restriction does not have a value. For a setting with expression restrictions, some required setting values in the expressions evaluate to false.","title":"Restriction Violations"},{"location":"os/modules/sysinitconfig/sysconfig_error/#example-notnull-restriction-violation-error-message","text":"The following example shows the error message that newt outputs when a setting with $notnull restriction does not have a value: Error: Syscfg restriction violations detected: NFFS_FLASH_AREA must not be null Setting history (newest -> oldest): NFFS_FLASH_AREA: [fs/nffs:] The above error occurs because the fs/nffs package defines the NFFS_FLASH_AREA setting with a $notnull restriction and no packages override the setting. The following is an excerpt of the definition in the syscfg.yml file that causes the error: #Package: fs/nffs syscfg.defs: NFFS_FLASH_AREA: description: 'The flash area to use for the Newtron Flash File System' type: flash_owner value: restrictions: - $notnull","title":"Example: $notnull Restriction Violation Error Message"},{"location":"os/modules/sysinitconfig/sysconfig_error/#example-expression-restriction-violation-error-message","text":"The following example shows the error message that newt outputs for an expression restriction violation: Error: Syscfg restriction violations detected: CONFIG_FCB=1 requires CONFIG_FCB_FLASH_AREA be set, but CONFIG_FCB_FLASH_AREA= Setting history (newest -> oldest): CONFIG_FCB: [targets/sim_slinky:1, sys/config:0] CONFIG_FCB_FLASH_AREA: [sys/config:] The above error occurs because the sys/config package defines the CONFIG_FCB setting with a restriction that when set, requires that the CONFIG_FCB_FLASH_AREA setting must also be set. The following are excerpts of the definition and the override from the syscfg.yml files that cause the error: # Package: sys/config syscfg.defs: CONFIG_FCB: description: 'Uses Config Flash Circular Buffer' value: 0 restrictions: - '!CONFIG_NFFS' - 'CONFIG_FCB_FLASH_AREA' # Package: targets/sim_slinky syscfg.vals: CONFIG_FCB: 1","title":"Example: Expression Restriction Violation Error Message"},{"location":"os/modules/sysinitconfig/sysconfig_error/#task-priority-violations","text":"For task_priority type setting definitions, newt checks for the following violations: A task priority number is assigned to multiple settings. The task priority number is greater than 239.","title":"Task Priority Violations"},{"location":"os/modules/sysinitconfig/sysconfig_error/#example-duplicate-task-priority-assignment-error-message","text":"The following example shows the error message that newt outputs when a task priority number is assigned to multiple settings. Note: The settings used in this example are not actual apps/slinky and sys/shell settings. These settings are created for this example because currently only one Mynewt package defines a task_priority type setting. Error: duplicate priority value: setting1=SHELL_TASK_PRIORITY setting2=SLINKY_TASK_PRIORITY pkg1=apps/slinky pkg2=sys/shell value=1 The above error occurs because the apps/slinky package defines a SLINKY_TASK_PRIORITY setting with a default task priority of 1 and the sys/shell package also defines a SHELL_TASK_PRIORITY setting with a default task priority of 1.","title":"Example: Duplicate Task Priority Assignment Error Message"},{"location":"os/modules/sysinitconfig/sysconfig_error/#example-invalid-task-priority-error-message","text":"The following example shows the error message that newt outputs when a setting is assigned an invalid task priority value: Error: invalid priority value: value too great (> 239); setting=SLINKY_TASK_PRIORITY value=240 pkg=apps/slinky The above error occurs because the apps/slinky package defines the SLINKY_TASK_PRIORITY setting with 240 for the default task priority value. Note: Newt does not output the Setting history with task priority violation error messages.","title":"Example: Invalid Task Priority Error Message"},{"location":"os/modules/sysinitconfig/sysconfig_error/#duplicate-system-configuration-setting-definition","text":"A setting definition must be unique. Newt checks that only one package in the target defines a setting. The following example shows the error message that newt outputs when multiple packages define the LOG_NEWTMGR setting: Error: setting LOG_NEWTMGR redefined Note: Newt does not output the Setting history with duplicate setting error messages.","title":"Duplicate System Configuration Setting Definition"},{"location":"os/modules/sysinitconfig/sysconfig_error/#override-of-undefined-system-configuration-setting","text":"The newt build command ignores overrides of undefined system configuration settings. The command does not print a warning when you run it with the default log level. If you override a setting and the value is not assigned to the setting, you may have misspelled the setting name or a package no longer defines the setting. You have two options to troubleshoot this problem: Run the newt target config show command to see the configuration setting definitions and overrides. Run the newt build -ldebug command to build your target with DEBUG log level. Note: The newt build -ldebug command generates lots of output and we recommend that you use the newt target config show command option.","title":"Override of Undefined System Configuration Setting"},{"location":"os/modules/sysinitconfig/sysconfig_error/#example-ignoring-override-of-undefined-setting-message","text":"The following example shows that the apps/slinky application overrides the LOG_NEWTMGR setting but omits the T as an example of an error and overrides the misspelled LOG_NEWMGR setting. Here is an excerpt from its syscfg.yml file: #package: apps/slinky syscfg.vals: # Enable the shell task. SHELL_TASK: 1 ... # Enable newtmgr commands. STATS_NEWTMGR: 1 LOG_NEWMGR: 1 The newt target config show slinky_sim command outputs the following WARNING message: 2017/02/18 17:19:12.119 [WARNING] Ignoring override of undefined settings: 2017/02/18 17:19:12.119 [WARNING] LOG_NEWMGR 2017/02/18 17:19:12.119 [WARNING] NFFS_FLASH_AREA 2017/02/18 17:19:12.119 [WARNING] Setting history (newest -> oldest): 2017/02/18 17:19:12.119 [WARNING] LOG_NEWMGR: [apps/slinky:1] 2017/02/18 17:19:12.119 [WARNING] NFFS_FLASH_AREA: [hw/bsp/native:FLASH_AREA_NFFS] The newt build -ldebug slinky_sim command outputs the following DEBUG message: 2017/02/18 17:06:21.451 [DEBUG] Ignoring override of undefined settings: 2017/02/18 17:06:21.451 [DEBUG] LOG_NEWMGR 2017/02/18 17:06:21.451 [DEBUG] NFFS_FLASH_AREA 2017/02/18 17:06:21.451 [DEBUG] Setting history (newest -> oldest): 2017/02/18 17:06:21.451 [DEBUG] LOG_NEWMGR: [apps/slinky:1] 2017/02/18 17:06:21.451 [DEBUG] NFFS_FLASH_AREA: [hw/bsp/native:FLASH_AREA_NFFS]","title":"Example: Ignoring Override of Undefined Setting Message"},{"location":"os/modules/sysinitconfig/sysconfig_error/#bsp-package-overrides-undefined-configuration-settings","text":"You might see a warning that indicates your application's BSP package is overriding some undefined settings. As you can see from the previous example, the WARNING message shows that the hw/bsp/native package is overriding the undefined NFFS_FLASH_AREA setting. This is not an error because of the way a BSP package defines and assigns its flash areas to packages that use flash memory. A BSP package defines, in its bsp.yml file, a flash area map of the flash areas on the board. A package that uses flash memory must define a flash area configuration setting name. The BSP package overrides the package's flash area setting with one of the flash areas from its flash area map. A BSP package overrides the flash area settings for all packages that use flash memory because it does not know the packages that an application uses. When an application does not include one of these packages, the flash area setting for the package is undefined. You will see a message that indicates the BSP package overrides this undefined setting. Here are excerpts from the hw/bsp/native package's bsp.yml and syscfg.yml files for the slinky_sim target. The BSP package defines the flash area map in its bsp.yml file and overrides the flash area settings for all packages in its syscfg.yml file. The slinky_sim target does not use the fs/nffs package which defines the NFFS_FLASH_AREA setting. Newt warns that the hw/bsp/native packages overrides the undefined NFFS_FLASH_AREA setting. # hw/bsp/native bsp.yml bsp.flash_map: areas: # System areas. FLASH_AREA_BOOTLOADER: device: 0 offset: 0x00000000 size: 16kB ... FLASH_AREA_IMAGE_SCRATCH: device: 0 offset: 0x000e0000 size: 128kB # User areas. FLASH_AREA_REBOOT_LOG: user_id: 0 device: 0 offset: 0x00004000 size: 16kB FLASH_AREA_NFFS: user_id: 1 device: 0 offset: 0x00008000 # hw/bsp/native syscfg.yml syscfg.vals: NFFS_FLASH_AREA: FLASH_AREA_NFFS CONFIG_FCB_FLASH_AREA: FLASH_AREA_NFFS REBOOT_LOG_FLASH_AREA: FLASH_AREA_REBOOT_LOG","title":"BSP Package Overrides Undefined Configuration Settings"},{"location":"os/modules/sysinitconfig/sysinitconfig/","text":"System Configuration and Initialization This guide describes how Mynewt manages system configuration and initialization. It shows you how to tell Mynewt to use default or customized values to initialize packages that you develop or use to build a target. This guide: Assumes you have read the Concepts section that describes the Mynewt package hierarchy and its use of the pkg.yml and syscfg.yml files. Assumes you have read the Newt Tool Theory of Operation and are familiar with how newt determines package dependencies for your target build. Covers only the system initialization for hardware independent packages. It does not cover the Board Support Package (BSP) and other hardware dependent system initialization. Mynewt defines several configuration parameters in the pkg.yml and syscfg.yml files. The newt tool uses this information to: Generate a system initialization function that calls all the package-specific system initialization functions. Generate a system configuration header file that contains all the package configuration settings and values. Display the system configuration settings and values in the newt target config command. The benefits with this approach include: Allows Mynewt developers to reuse other packages and easily change their configuration settings without updating source or header files when implementing new packages. Allows application developers to easily view the system configuration settings and values and determine the values to override for a target build. System Configuration Setting Definitions and Values A package can optionally: Define and expose the system configuration settings to allow other packages to override the default setting values. Override the system configuration setting values defined by the packages that it depends on. You use the defs parameter in a syscfg.yml file to define the system configuration settings for a package. defs is a mapping (or associative array) of system configuration setting definitions. It has the following syntax: syscfg.defs: PKGA_SYSCFG_NAME1: description: value: type: restrictions: PKGA_SYSCFG_NAME2: description: value: type: restrictions: Each setting definition consists of the following key-value mapping: A setting name for the key, such as PKGA_SYSCFG_NAME1 in the syntax example above. Note: A system configuration setting name must be unique. The newt tool aborts the build when multiple packages define the same setting. A mapping of fields for the value. Each field itself is a key-value pair of attributes. The field keys are description , value , type , and restrictions . They are described in following table: Field Description description Describes the usage for the setting. This field is optional. value Specifies the default value for the setting. This field is required. The value depends on the type that you specify and can be an empty string. type Specifies the data type for the value field. This field is optional. You can specify one of three types: raw - The value data is uninterpreted. This is the default type . task_priority - Specifies a Mynewt task priority number. The task priority number assigned to each setting must be unique and between 0 and 239. value can be one of the following: A number between 0 and 239 - The task priority number to use for the setting. any - Specify any to have newt automatically assign a priority for the setting. newt alphabetically orders all system configuration settings of this type and assigns the next highest available task priority number to each setting. flash_owner - Specifies a flash area. The value should be the name of a flash area defined in the BSP flash map for your target board. restrictions Specifies a list of restrictions on the setting value. This field is optional. You can specify two formats: $notnull - Specifies that the setting cannot have the empty string for a value. It essentially means that an empty string is not a sensible value and a package must override it with an appropriate value. expression - Specifies a boolean expression of the form [!]<required-setting>[if <base-value>] Examples: restrictions: !LOG_FCB - When this setting is enabled, LOG_FCB must be disabled. restrictions: LOG_FCB if 0 - When this setting is disabled, LOG_FCB must be enabled. Examples of Configuration Settings Example 1: The following example is an excerpt from the sys/log/full package syscfg.yml file. It defines the LOG_LEVEL configuration setting to specify the log level and the LOG_NEWTMGR configuration setting to specify whether to enable or disable the newtmgr logging feature. syscfg.defs: LOG_LEVEL: description: 'Log Level' value: 0 type: raw ... LOG_NEWTMGR: description: 'Enables or disables newtmgr command tool logging' value: 0 Example 2: The following example is an excerpt from the net/nimble/controller package syscfg.yml file. It defines the BLE_LL_PRIO configuration setting with a task_priority type and assigns task priority 0 to the BLE link layer task. syscfg.defs: BLE_LL_PRIO: description: 'BLE link layer task priority' type: 'task_priority' value: 0 Example 3: The following example is an excerpt from the fs/nffs package syscfg.yml file. syscfg.defs: NFFS_FLASH_AREA: description: 'The flash area to use for the Newtron Flash File System' type: flash_owner value: restrictions: - $notnull It defines the NFFS_FLASH_AREA configuration setting with a flash_owner type indicating that a flash area needs to be specified for the Newtron Flash File System. The flash areas are typically defined by the BSP in its bsp.yml file. For example, the bsp.yml for nrf52dk board ( hw/bsp/nrf52dk/bsp.yml ) defines an area named FLASH_AREA_NFFS : FLASH_AREA_NFFS: user_id: 1 device: 0 offset: 0x0007d000 size: 12kB The syscfg.yml file for the same board ( hw/bsp/nrf52dk/syscfg.yml ) specifies that the above area be used for NFFS_FLASH_AREA . syscfg.vals: CONFIG_FCB_FLASH_AREA: FLASH_AREA_NFFS REBOOT_LOG_FLASH_AREA: FLASH_AREA_REBOOT_LOG NFFS_FLASH_AREA: FLASH_AREA_NFFS COREDUMP_FLASH_AREA: FLASH_AREA_IMAGE_1 Note that the fs/nffs/syscfg.yml file indicates that the NFFS_FLASH_AREA setting cannot be a null string; so a higher priority package must set a non-null value to it. That is exactly what the BSP package does. For more on priority of packages in setting values, see the next section. Overriding System Configuration Setting Values A package may use the vals parameter in its syscfg.yml file to override the configuration values defined by other packages. This mechanism allows: Mynewt developers to implement a package and easily override the system configuration setting values that are defined by the packages it depends on. Application developers to easily and cleanly override default configuration settings in a single place and build a customized target. You can use the newt target config show <target-name> command to check all the system configuration setting definitions and values in your target to determine the setting values to override. See newt target . vals specifies the mappings of system configuration setting name-value pairs as follows: syscfg.vals: PKGA_SYSCFG_NAME1: VALUE1 PKGA_SYSCFG_NAME2: VALUE2 ... PKGN_SYSCFG_NAME1: VALUEN Note : The newt tool ignores overrides of undefined system configuration settings. Resolving Override Conflicts The newt tool uses package priorities to determine whether a package can override a value and resolve conflicts when multiple packages override the same system configuration setting. The following rules apply: A package can only override the default values of system configuration settings that are defined by lower priority packages. When packages with different priorities override the same system configuration setting value, newt uses the value from the highest priority package. Packages of equal priority cannot override the same system configuration setting with different values. newt aborts the build unless a higher priority package also overrides the value. The following package types are listed from highest to lowest priority: Target App unittest - A target can include either an app or unit test package, but not both. BSP Lib - Includes all other system level packages such as os, lib, sdk, and compiler. (Note that a Lib package cannot override other Lib package settings.) It is recommended that you override defaults at the target level instead of updating individual package syscfg.yml files. Examples of Overrides Example 4: The following example is an excerpt from the apps/slinky package syscfg.yml file. The application package overrides, in addition to other packages, the sys/log/full package system configuration settings defined in Example 1 . It changes the LOG_NEWTMGR system configuration setting value from 0 to 1 . syscfg.vals: # Enable the shell task. SHELL_TASK: 1 ... # Enable newtmgr commands. STATS_NEWTMGR: 1 LOG_NEWTMGR: 1 Example 5: The following example are excerpts from the hw/bsp/native package bsp.yml and syscfg.yml files. The package defines the flash areas for the BSP flash map in the bsp.yml file, and sets the NFFS_FLASH_AREA configuration setting value to use the flash area named FLASH_AREA_NFFS in the syscfg.yml file. bsp.flash_map: areas: # System areas. FLASH_AREA_BOOTLOADER: device: 0 offset: 0x00000000 size: 16kB ... # User areas. FLASH_AREA_REBOOT_LOG: user_id: 0 device: 0 offset: 0x00004000 size: 16kB FLASH_AREA_NFFS: user_id: 1 device: 0 offset: 0x00008000 size: 32kB syscfg.vals: NFFS_FLASH_AREA: FLASH_AREA_NFFS Generated syscfg.h and Referencing System Configuration Settings The newt tool processes all the package syscfg.yml files and generates the <target-path>/generated/include/syscfg/syscfg.h include file with #define statements for each system configuration setting defined. Newt creates a #define for a setting name as follows: Adds the prefix MYNEWT_VAL_ . Replaces all occurrences of \"/\", \"-\", and \" \" in the setting name with \"_\". Converts all characters to upper case. For example, the #define for my-config-name setting name is MYNEWT_VAL_MY_CONFIG_NAME. Newt groups the settings in syscfg.h by the packages that defined them. It also indicates the package that changed a system configuration setting value. You must use the MYNEWT_VAL() macro to reference a #define of a setting name in your header and source files. For example, to reference the my-config-name setting name, you use MYNEWT_VAL(MY_CONFIG_NAME) . Note: You only need to include syscfg/syscfg.h in your source files to access the syscfg.h file. The newt tool sets the correct include path to build your target. Example of syscfg.h and How to Reference a Setting Name Example 6 : The following example are excerpts from a sample syscfg.h file generated for an app/slinky target and from the sys/log/full package log.c file that shows how to reference a setting name. The syscfg.h file shows the sys/log/full package definitions and also indicates that app/slinky changed the value for the LOG_NEWTMGR settings. /** * This file was generated by Apache Newt (incubating) version: 1.0.0-dev */ #ifndef H_MYNEWT_SYSCFG_ #define H_MYNEWT_SYSCFG_ /** * This macro exists to ensure code includes this header when needed. If code * checks the existence of a setting directly via ifdef without including this * header, the setting macro will silently evaluate to 0. In contrast, an * attempt to use these macros without including this header will result in a * compiler error. */ #define MYNEWT_VAL(x) MYNEWT_VAL_ ## x ... /*** kernel/os */ #ifndef MYNEWT_VAL_MSYS_1_BLOCK_COUNT #define MYNEWT_VAL_MSYS_1_BLOCK_COUNT (12) #endif #ifndef MYNEWT_VAL_MSYS_1_BLOCK_SIZE #define MYNEWT_VAL_MSYS_1_BLOCK_SIZE (292) #endif ... /*** sys/log/full */ #ifndef MYNEWT_VAL_LOG_LEVEL #define MYNEWT_VAL_LOG_LEVEL (0) #endif ... /* Overridden by apps/slinky (defined by sys/log/full) */ #ifndef MYNEWT_VAL_LOG_NEWTMGR #define MYNEWT_VAL_LOG_NEWTMGR (1) #endif #endif The log_init() function in the sys/log/full/src/log.c file initializes the sys/log/full package. It checks the LOG_NEWTMGR setting value, using MYNEWT_VAL(LOG_NEWTMGR) , to determine whether the target application has enabled the newtmgr log functionality. It only registers the the callbacks to process the newtmgr log commands when the setting value is non-zero. void log_init(void) { int rc; /* Ensure this function only gets called by sysinit. */ SYSINIT_ASSERT_ACTIVE(); (void)rc; if (log_inited) { return; } log_inited = 1; ... #if MYNEWT_VAL(LOG_NEWTMGR) rc = log_nmgr_register_group(); SYSINIT_PANIC_ASSERT(rc == 0); #endif } System Initialization During system startup, Mynewt creates a default event queue and a main task to process events from this queue. You can override the OS_MAIN_TASK_PRIO and OS_MAIN_TASK_STACK_SIZE setting values defined by the kernel/os package to specify different task priority and stack size values. Your application's main() function executes in the context of the main task and must perform the following: At the start of main() , call the Mynewt sysinit() function to initialize the packages before performing any other processing. At the end of main() , wait for and dispatch events from the default event queue in an infinite loop. Note: You must include the sysinit/sysinit.h header file to access the sysinit() function. Here is an example of a main() function: int main(int argc, char **argv) { /* First, call sysinit() to perform the system and package initialization */ sysinit(); ... other application initialization processing.... /* Last, process events from the default event queue. */ while (1) { os_eventq_run(os_eventq_dflt_get()); } /* main never returns */ } Specifying Package Initialization Functions The sysinit() function calls the sysinit_app() function to perform system initialization for the packages in the target. You can, optionally, specify one or more package initialization functions that sysinit_app() calls to initialize a package. A package initialization function must have the following prototype: void init_func_name(void) Package initialization functions are called in stages to ensure that lower priority packages are initialized before higher priority packages. A stage is an integer value, 0 or higher, that specifies when an initialization function is called. Mynewt calls the package initialization functions in increasing stage number order. The call order for initialization functions with the same stage number depends on the order the packages are processed, and you cannot rely on a specific call order for these functions. You use the pkg.init parameter in the pkg.yml file to specify an initialization function and the stage number to call the function. You can specify multiple initialization functions, with a different stage number for each function, for the parameter values. This feature allows packages with interdependencies to perform initialization in multiple stages. The pkg.init parameter has the following syntax in the pkg.yml file: pkg.init: pkg_init_func1_name: pkg_init_func1_stage pkg_init_func2_name: pkg_init_func2_stage ... pkg_init_funcN_name: pkg_init_funcN_stage where pkg_init_func#_name is the C function name of an initialization function, and pkg_init_func#_stage is an integer value, 0 or higher, that indicates the stage when the pkg_init_func#_name function is called. Note: The pkg.init_function and pkg.init_stage parameters introduced in a previous release for specifying a package initialization function and a stage number are deprecated and have been retained to support the legacy format. They will not be maintained for future releases and we recommend that you migrate to use the pkg.init parameter. Generated sysinit_app() Function The newt tool processes the pkg.init parameters in all the pkg.yml files for a target, generates the sysinit_app() function in the <target-path>/generated/src/<target-name>-sysinit_app.c file, and includes the file in the build. Here is an example sysinit_app() function: ** * This file was generated by Apache Newt (incubating) version: 1.0.0-dev */ #if !SPLIT_LOADER void split_app_init(void); void os_pkg_init(void); void imgmgr_module_init(void); ... void stats_module_init(void); void sysinit_app(void) { /*** Stage 0 */ /* 0.0: kernel/os */ os_pkg_init(); /*** Stage 2 */ /* 2.0: sys/flash_map */ flash_map_init(); /*** Stage 10 */ /* 10.0: sys/stats/full */ stats_module_init(); /*** Stage 20 */ /* 20.0: sys/console/full */ console_pkg_init(); /*** Stage 100 */ /* 100.0: sys/log/full */ log_init(); /* 100.1: sys/mfg */ mfg_init(); .... /*** Stage 300 */ /* 300.0: sys/config */ config_pkg_init(); /*** Stage 500 */ /* 500.0: sys/id */ id_init(); /* 500.1: sys/shell */ shell_init(); ... /* 500.4: mgmt/imgmgr */ imgmgr_module_init(); /*** Stage 501 */ /* 501.0: mgmt/newtmgr/transport/nmgr_shell */ nmgr_shell_pkg_init(); } #endif Conditional Configurations You can use the system configuration setting values to conditionally specify parameter values in pkg.yml and syscfg.yml files. The syntax is: parameter_name.PKGA_SYSCFG_NAME: parameter_value This specifies that parameter_value is only set for parameter_name if the PKGA_SYSCFG_NAME configuration setting value is non-zero. Here is an example from the libs/os package pkg.yml file: pkg.deps: - sys/sysinit - util/mem pkg.deps.OS_CLI - sys/shell This example specifies that the os package depends on the sysinit and mem packages, and also depends on the shell package when OS_CLI is enabled. The newt tool aborts the build when it detects circular conditional dependencies.","title":"toc"},{"location":"os/modules/sysinitconfig/sysinitconfig/#system-configuration-and-initialization","text":"This guide describes how Mynewt manages system configuration and initialization. It shows you how to tell Mynewt to use default or customized values to initialize packages that you develop or use to build a target. This guide: Assumes you have read the Concepts section that describes the Mynewt package hierarchy and its use of the pkg.yml and syscfg.yml files. Assumes you have read the Newt Tool Theory of Operation and are familiar with how newt determines package dependencies for your target build. Covers only the system initialization for hardware independent packages. It does not cover the Board Support Package (BSP) and other hardware dependent system initialization. Mynewt defines several configuration parameters in the pkg.yml and syscfg.yml files. The newt tool uses this information to: Generate a system initialization function that calls all the package-specific system initialization functions. Generate a system configuration header file that contains all the package configuration settings and values. Display the system configuration settings and values in the newt target config command. The benefits with this approach include: Allows Mynewt developers to reuse other packages and easily change their configuration settings without updating source or header files when implementing new packages. Allows application developers to easily view the system configuration settings and values and determine the values to override for a target build.","title":"System Configuration and Initialization"},{"location":"os/modules/sysinitconfig/sysinitconfig/#system-configuration-setting-definitions-and-values","text":"A package can optionally: Define and expose the system configuration settings to allow other packages to override the default setting values. Override the system configuration setting values defined by the packages that it depends on. You use the defs parameter in a syscfg.yml file to define the system configuration settings for a package. defs is a mapping (or associative array) of system configuration setting definitions. It has the following syntax: syscfg.defs: PKGA_SYSCFG_NAME1: description: value: type: restrictions: PKGA_SYSCFG_NAME2: description: value: type: restrictions: Each setting definition consists of the following key-value mapping: A setting name for the key, such as PKGA_SYSCFG_NAME1 in the syntax example above. Note: A system configuration setting name must be unique. The newt tool aborts the build when multiple packages define the same setting. A mapping of fields for the value. Each field itself is a key-value pair of attributes. The field keys are description , value , type , and restrictions . They are described in following table: Field Description description Describes the usage for the setting. This field is optional. value Specifies the default value for the setting. This field is required. The value depends on the type that you specify and can be an empty string. type Specifies the data type for the value field. This field is optional. You can specify one of three types: raw - The value data is uninterpreted. This is the default type . task_priority - Specifies a Mynewt task priority number. The task priority number assigned to each setting must be unique and between 0 and 239. value can be one of the following: A number between 0 and 239 - The task priority number to use for the setting. any - Specify any to have newt automatically assign a priority for the setting. newt alphabetically orders all system configuration settings of this type and assigns the next highest available task priority number to each setting. flash_owner - Specifies a flash area. The value should be the name of a flash area defined in the BSP flash map for your target board. restrictions Specifies a list of restrictions on the setting value. This field is optional. You can specify two formats: $notnull - Specifies that the setting cannot have the empty string for a value. It essentially means that an empty string is not a sensible value and a package must override it with an appropriate value. expression - Specifies a boolean expression of the form [!]<required-setting>[if <base-value>] Examples: restrictions: !LOG_FCB - When this setting is enabled, LOG_FCB must be disabled. restrictions: LOG_FCB if 0 - When this setting is disabled, LOG_FCB must be enabled.","title":"System Configuration Setting Definitions and Values"},{"location":"os/modules/sysinitconfig/sysinitconfig/#examples-of-configuration-settings","text":"Example 1: The following example is an excerpt from the sys/log/full package syscfg.yml file. It defines the LOG_LEVEL configuration setting to specify the log level and the LOG_NEWTMGR configuration setting to specify whether to enable or disable the newtmgr logging feature. syscfg.defs: LOG_LEVEL: description: 'Log Level' value: 0 type: raw ... LOG_NEWTMGR: description: 'Enables or disables newtmgr command tool logging' value: 0 Example 2: The following example is an excerpt from the net/nimble/controller package syscfg.yml file. It defines the BLE_LL_PRIO configuration setting with a task_priority type and assigns task priority 0 to the BLE link layer task. syscfg.defs: BLE_LL_PRIO: description: 'BLE link layer task priority' type: 'task_priority' value: 0 Example 3: The following example is an excerpt from the fs/nffs package syscfg.yml file. syscfg.defs: NFFS_FLASH_AREA: description: 'The flash area to use for the Newtron Flash File System' type: flash_owner value: restrictions: - $notnull It defines the NFFS_FLASH_AREA configuration setting with a flash_owner type indicating that a flash area needs to be specified for the Newtron Flash File System. The flash areas are typically defined by the BSP in its bsp.yml file. For example, the bsp.yml for nrf52dk board ( hw/bsp/nrf52dk/bsp.yml ) defines an area named FLASH_AREA_NFFS : FLASH_AREA_NFFS: user_id: 1 device: 0 offset: 0x0007d000 size: 12kB The syscfg.yml file for the same board ( hw/bsp/nrf52dk/syscfg.yml ) specifies that the above area be used for NFFS_FLASH_AREA . syscfg.vals: CONFIG_FCB_FLASH_AREA: FLASH_AREA_NFFS REBOOT_LOG_FLASH_AREA: FLASH_AREA_REBOOT_LOG NFFS_FLASH_AREA: FLASH_AREA_NFFS COREDUMP_FLASH_AREA: FLASH_AREA_IMAGE_1 Note that the fs/nffs/syscfg.yml file indicates that the NFFS_FLASH_AREA setting cannot be a null string; so a higher priority package must set a non-null value to it. That is exactly what the BSP package does. For more on priority of packages in setting values, see the next section.","title":"Examples of Configuration Settings"},{"location":"os/modules/sysinitconfig/sysinitconfig/#overriding-system-configuration-setting-values","text":"A package may use the vals parameter in its syscfg.yml file to override the configuration values defined by other packages. This mechanism allows: Mynewt developers to implement a package and easily override the system configuration setting values that are defined by the packages it depends on. Application developers to easily and cleanly override default configuration settings in a single place and build a customized target. You can use the newt target config show <target-name> command to check all the system configuration setting definitions and values in your target to determine the setting values to override. See newt target . vals specifies the mappings of system configuration setting name-value pairs as follows: syscfg.vals: PKGA_SYSCFG_NAME1: VALUE1 PKGA_SYSCFG_NAME2: VALUE2 ... PKGN_SYSCFG_NAME1: VALUEN Note : The newt tool ignores overrides of undefined system configuration settings.","title":"Overriding System Configuration Setting Values"},{"location":"os/modules/sysinitconfig/sysinitconfig/#resolving-override-conflicts","text":"The newt tool uses package priorities to determine whether a package can override a value and resolve conflicts when multiple packages override the same system configuration setting. The following rules apply: A package can only override the default values of system configuration settings that are defined by lower priority packages. When packages with different priorities override the same system configuration setting value, newt uses the value from the highest priority package. Packages of equal priority cannot override the same system configuration setting with different values. newt aborts the build unless a higher priority package also overrides the value. The following package types are listed from highest to lowest priority: Target App unittest - A target can include either an app or unit test package, but not both. BSP Lib - Includes all other system level packages such as os, lib, sdk, and compiler. (Note that a Lib package cannot override other Lib package settings.) It is recommended that you override defaults at the target level instead of updating individual package syscfg.yml files.","title":"Resolving Override Conflicts"},{"location":"os/modules/sysinitconfig/sysinitconfig/#examples-of-overrides","text":"Example 4: The following example is an excerpt from the apps/slinky package syscfg.yml file. The application package overrides, in addition to other packages, the sys/log/full package system configuration settings defined in Example 1 . It changes the LOG_NEWTMGR system configuration setting value from 0 to 1 . syscfg.vals: # Enable the shell task. SHELL_TASK: 1 ... # Enable newtmgr commands. STATS_NEWTMGR: 1 LOG_NEWTMGR: 1 Example 5: The following example are excerpts from the hw/bsp/native package bsp.yml and syscfg.yml files. The package defines the flash areas for the BSP flash map in the bsp.yml file, and sets the NFFS_FLASH_AREA configuration setting value to use the flash area named FLASH_AREA_NFFS in the syscfg.yml file. bsp.flash_map: areas: # System areas. FLASH_AREA_BOOTLOADER: device: 0 offset: 0x00000000 size: 16kB ... # User areas. FLASH_AREA_REBOOT_LOG: user_id: 0 device: 0 offset: 0x00004000 size: 16kB FLASH_AREA_NFFS: user_id: 1 device: 0 offset: 0x00008000 size: 32kB syscfg.vals: NFFS_FLASH_AREA: FLASH_AREA_NFFS","title":"Examples of Overrides"},{"location":"os/modules/sysinitconfig/sysinitconfig/#generated-syscfgh-and-referencing-system-configuration-settings","text":"The newt tool processes all the package syscfg.yml files and generates the <target-path>/generated/include/syscfg/syscfg.h include file with #define statements for each system configuration setting defined. Newt creates a #define for a setting name as follows: Adds the prefix MYNEWT_VAL_ . Replaces all occurrences of \"/\", \"-\", and \" \" in the setting name with \"_\". Converts all characters to upper case. For example, the #define for my-config-name setting name is MYNEWT_VAL_MY_CONFIG_NAME. Newt groups the settings in syscfg.h by the packages that defined them. It also indicates the package that changed a system configuration setting value. You must use the MYNEWT_VAL() macro to reference a #define of a setting name in your header and source files. For example, to reference the my-config-name setting name, you use MYNEWT_VAL(MY_CONFIG_NAME) . Note: You only need to include syscfg/syscfg.h in your source files to access the syscfg.h file. The newt tool sets the correct include path to build your target.","title":"Generated syscfg.h and Referencing System Configuration Settings"},{"location":"os/modules/sysinitconfig/sysinitconfig/#example-of-syscfgh-and-how-to-reference-a-setting-name","text":"Example 6 : The following example are excerpts from a sample syscfg.h file generated for an app/slinky target and from the sys/log/full package log.c file that shows how to reference a setting name. The syscfg.h file shows the sys/log/full package definitions and also indicates that app/slinky changed the value for the LOG_NEWTMGR settings. /** * This file was generated by Apache Newt (incubating) version: 1.0.0-dev */ #ifndef H_MYNEWT_SYSCFG_ #define H_MYNEWT_SYSCFG_ /** * This macro exists to ensure code includes this header when needed. If code * checks the existence of a setting directly via ifdef without including this * header, the setting macro will silently evaluate to 0. In contrast, an * attempt to use these macros without including this header will result in a * compiler error. */ #define MYNEWT_VAL(x) MYNEWT_VAL_ ## x ... /*** kernel/os */ #ifndef MYNEWT_VAL_MSYS_1_BLOCK_COUNT #define MYNEWT_VAL_MSYS_1_BLOCK_COUNT (12) #endif #ifndef MYNEWT_VAL_MSYS_1_BLOCK_SIZE #define MYNEWT_VAL_MSYS_1_BLOCK_SIZE (292) #endif ... /*** sys/log/full */ #ifndef MYNEWT_VAL_LOG_LEVEL #define MYNEWT_VAL_LOG_LEVEL (0) #endif ... /* Overridden by apps/slinky (defined by sys/log/full) */ #ifndef MYNEWT_VAL_LOG_NEWTMGR #define MYNEWT_VAL_LOG_NEWTMGR (1) #endif #endif The log_init() function in the sys/log/full/src/log.c file initializes the sys/log/full package. It checks the LOG_NEWTMGR setting value, using MYNEWT_VAL(LOG_NEWTMGR) , to determine whether the target application has enabled the newtmgr log functionality. It only registers the the callbacks to process the newtmgr log commands when the setting value is non-zero. void log_init(void) { int rc; /* Ensure this function only gets called by sysinit. */ SYSINIT_ASSERT_ACTIVE(); (void)rc; if (log_inited) { return; } log_inited = 1; ... #if MYNEWT_VAL(LOG_NEWTMGR) rc = log_nmgr_register_group(); SYSINIT_PANIC_ASSERT(rc == 0); #endif }","title":"Example of syscfg.h and How to Reference a Setting Name"},{"location":"os/modules/sysinitconfig/sysinitconfig/#system-initialization","text":"During system startup, Mynewt creates a default event queue and a main task to process events from this queue. You can override the OS_MAIN_TASK_PRIO and OS_MAIN_TASK_STACK_SIZE setting values defined by the kernel/os package to specify different task priority and stack size values. Your application's main() function executes in the context of the main task and must perform the following: At the start of main() , call the Mynewt sysinit() function to initialize the packages before performing any other processing. At the end of main() , wait for and dispatch events from the default event queue in an infinite loop. Note: You must include the sysinit/sysinit.h header file to access the sysinit() function. Here is an example of a main() function: int main(int argc, char **argv) { /* First, call sysinit() to perform the system and package initialization */ sysinit(); ... other application initialization processing.... /* Last, process events from the default event queue. */ while (1) { os_eventq_run(os_eventq_dflt_get()); } /* main never returns */ }","title":"System Initialization"},{"location":"os/modules/sysinitconfig/sysinitconfig/#specifying-package-initialization-functions","text":"The sysinit() function calls the sysinit_app() function to perform system initialization for the packages in the target. You can, optionally, specify one or more package initialization functions that sysinit_app() calls to initialize a package. A package initialization function must have the following prototype: void init_func_name(void) Package initialization functions are called in stages to ensure that lower priority packages are initialized before higher priority packages. A stage is an integer value, 0 or higher, that specifies when an initialization function is called. Mynewt calls the package initialization functions in increasing stage number order. The call order for initialization functions with the same stage number depends on the order the packages are processed, and you cannot rely on a specific call order for these functions. You use the pkg.init parameter in the pkg.yml file to specify an initialization function and the stage number to call the function. You can specify multiple initialization functions, with a different stage number for each function, for the parameter values. This feature allows packages with interdependencies to perform initialization in multiple stages. The pkg.init parameter has the following syntax in the pkg.yml file: pkg.init: pkg_init_func1_name: pkg_init_func1_stage pkg_init_func2_name: pkg_init_func2_stage ... pkg_init_funcN_name: pkg_init_funcN_stage where pkg_init_func#_name is the C function name of an initialization function, and pkg_init_func#_stage is an integer value, 0 or higher, that indicates the stage when the pkg_init_func#_name function is called. Note: The pkg.init_function and pkg.init_stage parameters introduced in a previous release for specifying a package initialization function and a stage number are deprecated and have been retained to support the legacy format. They will not be maintained for future releases and we recommend that you migrate to use the pkg.init parameter.","title":"Specifying Package Initialization Functions"},{"location":"os/modules/sysinitconfig/sysinitconfig/#generated-sysinit_app-function","text":"The newt tool processes the pkg.init parameters in all the pkg.yml files for a target, generates the sysinit_app() function in the <target-path>/generated/src/<target-name>-sysinit_app.c file, and includes the file in the build. Here is an example sysinit_app() function: ** * This file was generated by Apache Newt (incubating) version: 1.0.0-dev */ #if !SPLIT_LOADER void split_app_init(void); void os_pkg_init(void); void imgmgr_module_init(void); ... void stats_module_init(void); void sysinit_app(void) { /*** Stage 0 */ /* 0.0: kernel/os */ os_pkg_init(); /*** Stage 2 */ /* 2.0: sys/flash_map */ flash_map_init(); /*** Stage 10 */ /* 10.0: sys/stats/full */ stats_module_init(); /*** Stage 20 */ /* 20.0: sys/console/full */ console_pkg_init(); /*** Stage 100 */ /* 100.0: sys/log/full */ log_init(); /* 100.1: sys/mfg */ mfg_init(); .... /*** Stage 300 */ /* 300.0: sys/config */ config_pkg_init(); /*** Stage 500 */ /* 500.0: sys/id */ id_init(); /* 500.1: sys/shell */ shell_init(); ... /* 500.4: mgmt/imgmgr */ imgmgr_module_init(); /*** Stage 501 */ /* 501.0: mgmt/newtmgr/transport/nmgr_shell */ nmgr_shell_pkg_init(); } #endif","title":"Generated sysinit_app() Function"},{"location":"os/modules/sysinitconfig/sysinitconfig/#conditional-configurations","text":"You can use the system configuration setting values to conditionally specify parameter values in pkg.yml and syscfg.yml files. The syntax is: parameter_name.PKGA_SYSCFG_NAME: parameter_value This specifies that parameter_value is only set for parameter_name if the PKGA_SYSCFG_NAME configuration setting value is non-zero. Here is an example from the libs/os package pkg.yml file: pkg.deps: - sys/sysinit - util/mem pkg.deps.OS_CLI - sys/shell This example specifies that the os package depends on the sysinit and mem packages, and also depends on the shell package when OS_CLI is enabled. The newt tool aborts the build when it detects circular conditional dependencies.","title":"Conditional Configurations"},{"location":"os/modules/testutil/test_assert/","text":"TEST_ASSERT TEST_ASSERT(expression, fail_msg, ...) TEST_ASSERT_FATAL(expression, fail_msg, ...) Asserts that the specified condition is true. If the expression is true, nothing gets reported. fail_msg will be printed out if the expression is false. The expression argument is mandatory; the rest are optional. The fail_msg argument is a printf format string which specifies how the remaining arguments are parsed. TEST_ASSERT_FATAL() causes the current test case to be aborted, if expression fails. Arguments Arguments Description expression Condition being tested. If it fails, test is considered a failure, and a message is printed out. fail_msg Pointer to C string that contains a format string that follows the same specifications as format in printf. ... Depending on the format string, the function may expect either a sequence of additional arguments to be used to replace a format specifier in the format string or a variable arguments list. va_list is a special type defined in in stdarg.h. Returned values None Notes While console_printf , with its well understood formatting options in C, is more convenient and easy on the eyes than the raw output of console_write , the associated code size is considerably larger. Example Example #1: TEST_CASE(config_test_insert) { int rc; rc = conf_register(&config_test_handler); TEST_ASSERT(rc == 0); } Example #2: TEST_CASE(nffs_test_unlink) { int rc; .... rc = nffs_format(nffs_area_descs); TEST_ASSERT_FATAL(rc == 0); .... } Example #3: static int cbmem_test_case_1_walk(struct cbmem *cbmem, struct cbmem_entry_hdr *hdr, void *arg) { .... rc = cbmem_read(cbmem, hdr, &actual, 0, sizeof(actual)); TEST_ASSERT_FATAL(rc == 1, \"Couldn't read 1 byte from cbmem\"); TEST_ASSERT_FATAL(actual == expected, \"Actual doesn't equal expected (%d = %d)\", actual, expected); .... }","title":"TEST_ASSERT"},{"location":"os/modules/testutil/test_assert/#test_assert","text":"TEST_ASSERT(expression, fail_msg, ...) TEST_ASSERT_FATAL(expression, fail_msg, ...) Asserts that the specified condition is true. If the expression is true, nothing gets reported. fail_msg will be printed out if the expression is false. The expression argument is mandatory; the rest are optional. The fail_msg argument is a printf format string which specifies how the remaining arguments are parsed. TEST_ASSERT_FATAL() causes the current test case to be aborted, if expression fails.","title":" TEST_ASSERT"},{"location":"os/modules/testutil/test_assert/#arguments","text":"Arguments Description expression Condition being tested. If it fails, test is considered a failure, and a message is printed out. fail_msg Pointer to C string that contains a format string that follows the same specifications as format in printf. ... Depending on the format string, the function may expect either a sequence of additional arguments to be used to replace a format specifier in the format string or a variable arguments list. va_list is a special type defined in in stdarg.h.","title":"Arguments"},{"location":"os/modules/testutil/test_assert/#returned-values","text":"None","title":"Returned values"},{"location":"os/modules/testutil/test_assert/#notes","text":"While console_printf , with its well understood formatting options in C, is more convenient and easy on the eyes than the raw output of console_write , the associated code size is considerably larger.","title":"Notes"},{"location":"os/modules/testutil/test_assert/#example","text":"Example #1: TEST_CASE(config_test_insert) { int rc; rc = conf_register(&config_test_handler); TEST_ASSERT(rc == 0); } Example #2: TEST_CASE(nffs_test_unlink) { int rc; .... rc = nffs_format(nffs_area_descs); TEST_ASSERT_FATAL(rc == 0); .... } Example #3: static int cbmem_test_case_1_walk(struct cbmem *cbmem, struct cbmem_entry_hdr *hdr, void *arg) { .... rc = cbmem_read(cbmem, hdr, &actual, 0, sizeof(actual)); TEST_ASSERT_FATAL(rc == 1, \"Couldn't read 1 byte from cbmem\"); TEST_ASSERT_FATAL(actual == expected, \"Actual doesn't equal expected (%d = %d)\", actual, expected); .... }","title":"Example"},{"location":"os/modules/testutil/test_case/","text":"TEST_CASE TEST_CASE(test_case_name) Defines a test case function with the following type int test_case_name(void) . This can then be called from regression test's TEST_SUITE() function. Arguments Arguments Description test_case_name Used as the function name for this test case. Returned values Return value is 0 if the test case passed; nonzero if it failed. Generally, the return code is not used. It is expected that the case will pass/fail with tests done using TEST_ASSERT() . Example TEST_CASE(config_test_insert) { .... }","title":"TEST_CASE"},{"location":"os/modules/testutil/test_case/#test_case","text":"TEST_CASE(test_case_name) Defines a test case function with the following type int test_case_name(void) . This can then be called from regression test's TEST_SUITE() function.","title":" TEST_CASE "},{"location":"os/modules/testutil/test_case/#arguments","text":"Arguments Description test_case_name Used as the function name for this test case.","title":"Arguments"},{"location":"os/modules/testutil/test_case/#returned-values","text":"Return value is 0 if the test case passed; nonzero if it failed. Generally, the return code is not used. It is expected that the case will pass/fail with tests done using TEST_ASSERT() .","title":"Returned values"},{"location":"os/modules/testutil/test_case/#example","text":"TEST_CASE(config_test_insert) { .... }","title":"Example"},{"location":"os/modules/testutil/test_decl/","text":"TEST_CASE_DECL TEST_CASE_DECL(test_case_name) Declares a test case function with the following type int test_case_name(void) . This can then be called from regression test's TEST_SUITE() function. This is only required if the test case function exists in a different file than the test suite. This will allow the test suite to find the test case Arguments Arguments Description test_case_name Used as the function name for this test case. Returned values Return value is 0 if the test case passed; nonzero if it failed. Generally, the return code is not used. It is expected that the case will pass/fail with tests done using TEST_ASSERT() . Example file test_cases.h TEST_CASE_DECL(test_case_1) TEST_CASE_DECL(test_case_2) TEST_CASE_DECL(test_case_3)","title":"TEST_CASE_DECL"},{"location":"os/modules/testutil/test_decl/#test_case_decl","text":"TEST_CASE_DECL(test_case_name) Declares a test case function with the following type int test_case_name(void) . This can then be called from regression test's TEST_SUITE() function. This is only required if the test case function exists in a different file than the test suite. This will allow the test suite to find the test case","title":" TEST_CASE_DECL "},{"location":"os/modules/testutil/test_decl/#arguments","text":"Arguments Description test_case_name Used as the function name for this test case.","title":"Arguments"},{"location":"os/modules/testutil/test_decl/#returned-values","text":"Return value is 0 if the test case passed; nonzero if it failed. Generally, the return code is not used. It is expected that the case will pass/fail with tests done using TEST_ASSERT() .","title":"Returned values"},{"location":"os/modules/testutil/test_decl/#example-file-test_casesh","text":"TEST_CASE_DECL(test_case_1) TEST_CASE_DECL(test_case_2) TEST_CASE_DECL(test_case_3)","title":"Example file test_cases.h"},{"location":"os/modules/testutil/test_pass/","text":"TEST_PASS TEST_PASS(msg, ...) Reports a success result for the current test. This function is not normally needed, as all successful tests automatically write an empty pass result at completion. It is only needed when the success result report should contain text. The msg argument is a printf format string which specifies how the remaining arguments are parsed. The result file produced by this function contains the following text: |<file>:<line-number>| manual pass <msg> Arguments Arguments Description msg This is a printf format string which specifies how the remaining arguments are parsed ... Depending on the format string, the function may expect either a sequence of additional arguments to be used to replace a format specifier in the format string or a variable arguments list. va_list is a special type defined in in stdarg.h. Returned values None Notes After this function is called, the remainder of the test case is not executed.","title":"TEST_PASS"},{"location":"os/modules/testutil/test_pass/#test_pass","text":"TEST_PASS(msg, ...) Reports a success result for the current test. This function is not normally needed, as all successful tests automatically write an empty pass result at completion. It is only needed when the success result report should contain text. The msg argument is a printf format string which specifies how the remaining arguments are parsed. The result file produced by this function contains the following text: |<file>:<line-number>| manual pass <msg>","title":" TEST_PASS "},{"location":"os/modules/testutil/test_pass/#arguments","text":"Arguments Description msg This is a printf format string which specifies how the remaining arguments are parsed ... Depending on the format string, the function may expect either a sequence of additional arguments to be used to replace a format specifier in the format string or a variable arguments list. va_list is a special type defined in in stdarg.h.","title":"Arguments"},{"location":"os/modules/testutil/test_pass/#returned-values","text":"None","title":"Returned values"},{"location":"os/modules/testutil/test_pass/#notes","text":"After this function is called, the remainder of the test case is not executed.","title":"Notes"},{"location":"os/modules/testutil/test_suite/","text":"TEST_SUITE TEST_SUITE(test_suite_name) Declares a test suite function with the following type int test_suite_name(void) . This can then be called from either project/test , or from main routine for package specific regression test. Arguments Arguments Description test_suite_name Used as the function name for this test suite. Returned values Return value is 0 if the test suite passed; nonzero if it failed. Generally, the return code is not used. It is expected that the individual test cases will pass/fail with tests done using TEST_ASSERT() . Example TEST_SUITE(os_sem_test_suite) { os_sem_test_basic(); os_sem_test_case_1(); os_sem_test_case_2(); os_sem_test_case_3(); os_sem_test_case_4(); }","title":"TEST_SUITE"},{"location":"os/modules/testutil/test_suite/#test_suite","text":"TEST_SUITE(test_suite_name) Declares a test suite function with the following type int test_suite_name(void) . This can then be called from either project/test , or from main routine for package specific regression test.","title":" TEST_SUITE "},{"location":"os/modules/testutil/test_suite/#arguments","text":"Arguments Description test_suite_name Used as the function name for this test suite.","title":"Arguments"},{"location":"os/modules/testutil/test_suite/#returned-values","text":"Return value is 0 if the test suite passed; nonzero if it failed. Generally, the return code is not used. It is expected that the individual test cases will pass/fail with tests done using TEST_ASSERT() .","title":"Returned values"},{"location":"os/modules/testutil/test_suite/#example","text":"TEST_SUITE(os_sem_test_suite) { os_sem_test_basic(); os_sem_test_case_1(); os_sem_test_case_2(); os_sem_test_case_3(); os_sem_test_case_4(); }","title":"Example"},{"location":"os/modules/testutil/testutil/","text":"testutil The testutil package is a test framework that provides facilities for specifying test cases and recording test results. You would use it to build regression tests for your library. Description A package may optionally contain a set of test cases. Test cases are not normally compiled and linked when a package is built; they are only included when the \"test\" identity is specified. All of a package's test code goes in its src/test directory. For example, the nffs package's test code is located in the following directory: * fs/nffs/src/test/ This directory contains the source and header files that implement the nffs test code. The test code has access to all the header files in the following directories: * src * src/arch/<target-arch> * include * src/test * src/test/arch/<target-arch> * include directories of all package dependencies Package test code typically depends on the testutil package, described later in this document. Some test cases or test initialization code may be platform-specific. In such cases, the platform-specific function definitions are placed in arch subdirectories within the package test directory. While building the test code (i.e., when the test identity is specified), the newt tool defines the TEST macro. This macro is defined during compilation of all C source files in all projects and packages. Tests are structured according to the following hierarchy: [test] / \\ [suite] [suite] / \\ / \\ [case] [case] [case] [case] I.e., a test consists of test suites, and a test suite consists of test cases. The test code uses testutil to define test suites and test cases. Regression test can then be executed using 'newt target test' command, or by including a call to your test suite from project/test/src/test.c . Example This Tutorial shows how to create a test suite for a Mynewt package. Data structures struct tu_config { int tc_print_results; int tc_system_assert; tu_case_init_fn_t *tc_case_init_cb; void *tc_case_init_arg; tu_case_report_fn_t *tc_case_fail_cb; void *tc_case_fail_arg; tu_case_report_fn_t *tc_case_pass_cb; void *tc_case_pass_arg; tu_suite_init_fn_t *tc_suite_init_cb; void *tc_suite_init_arg; tu_restart_fn_t *tc_restart_cb; void *tc_restart_arg; }; extern struct tu_config tu_config; The global tu_config struct contains all the testutil package's settings. This should be populated before tu_init() is called. List of Functions The functions, and macros available in testutil are: Function Description tu_init Initializes the test framework according to the contents of the tu_config struct. TEST_ASSERT Asserts that the specified condition is true. TEST_PASS Reports a success result for the current test. TEST_SUITE Declares a test suite function. TEST_CASE Defines a test case function. TEST_CASE_DECL Declares a test case function. his is only required if the test case function exists in a different file than the test suite. tu_restart This function is used when a system reset is necessary to proceed with testing.","title":"toc"},{"location":"os/modules/testutil/testutil/#testutil","text":"The testutil package is a test framework that provides facilities for specifying test cases and recording test results. You would use it to build regression tests for your library.","title":"testutil"},{"location":"os/modules/testutil/testutil/#description","text":"A package may optionally contain a set of test cases. Test cases are not normally compiled and linked when a package is built; they are only included when the \"test\" identity is specified. All of a package's test code goes in its src/test directory. For example, the nffs package's test code is located in the following directory: * fs/nffs/src/test/ This directory contains the source and header files that implement the nffs test code. The test code has access to all the header files in the following directories: * src * src/arch/<target-arch> * include * src/test * src/test/arch/<target-arch> * include directories of all package dependencies Package test code typically depends on the testutil package, described later in this document. Some test cases or test initialization code may be platform-specific. In such cases, the platform-specific function definitions are placed in arch subdirectories within the package test directory. While building the test code (i.e., when the test identity is specified), the newt tool defines the TEST macro. This macro is defined during compilation of all C source files in all projects and packages. Tests are structured according to the following hierarchy: [test] / \\ [suite] [suite] / \\ / \\ [case] [case] [case] [case] I.e., a test consists of test suites, and a test suite consists of test cases. The test code uses testutil to define test suites and test cases. Regression test can then be executed using 'newt target test' command, or by including a call to your test suite from project/test/src/test.c .","title":"Description"},{"location":"os/modules/testutil/testutil/#example","text":"This Tutorial shows how to create a test suite for a Mynewt package.","title":"Example"},{"location":"os/modules/testutil/testutil/#data-structures","text":"struct tu_config { int tc_print_results; int tc_system_assert; tu_case_init_fn_t *tc_case_init_cb; void *tc_case_init_arg; tu_case_report_fn_t *tc_case_fail_cb; void *tc_case_fail_arg; tu_case_report_fn_t *tc_case_pass_cb; void *tc_case_pass_arg; tu_suite_init_fn_t *tc_suite_init_cb; void *tc_suite_init_arg; tu_restart_fn_t *tc_restart_cb; void *tc_restart_arg; }; extern struct tu_config tu_config; The global tu_config struct contains all the testutil package's settings. This should be populated before tu_init() is called.","title":"Data structures"},{"location":"os/modules/testutil/testutil/#list-of-functions","text":"The functions, and macros available in testutil are: Function Description tu_init Initializes the test framework according to the contents of the tu_config struct. TEST_ASSERT Asserts that the specified condition is true. TEST_PASS Reports a success result for the current test. TEST_SUITE Declares a test suite function. TEST_CASE Defines a test case function. TEST_CASE_DECL Declares a test case function. his is only required if the test case function exists in a different file than the test suite. tu_restart This function is used when a system reset is necessary to proceed with testing.","title":"List of Functions"},{"location":"os/modules/testutil/tu_init/","text":"tu_init int tu_init(void) Initializes the test framework according to the contents of the tu_config struct. This function must be called before any tests are run. Arguments N/A Returned values Returns 0 on success; nonzero on failure. Example Here's an example of stand-alone code which allows the user to execute regression tests for sys/config package only. #ifdef PKG_TEST int main(int argc, char **argv) { tu_config.tc_print_results = 1; tu_init(); conf_init(); config_test_all(); return tu_any_failed; } #endif","title":"tu_init"},{"location":"os/modules/testutil/tu_init/#tu_init","text":"int tu_init(void) Initializes the test framework according to the contents of the tu_config struct. This function must be called before any tests are run.","title":" tu_init"},{"location":"os/modules/testutil/tu_init/#arguments","text":"N/A","title":"Arguments"},{"location":"os/modules/testutil/tu_init/#returned-values","text":"Returns 0 on success; nonzero on failure.","title":"Returned values"},{"location":"os/modules/testutil/tu_init/#example","text":"Here's an example of stand-alone code which allows the user to execute regression tests for sys/config package only. #ifdef PKG_TEST int main(int argc, char **argv) { tu_config.tc_print_results = 1; tu_init(); conf_init(); config_test_all(); return tu_any_failed; } #endif","title":"Example"},{"location":"os/modules/testutil/tu_restart/","text":"tu_restart void tu_restart(void) This function is used when a system reset is necessary to proceed with testing. For example, the OS is designed to run forever once started, so a test which creates several OS tasks and then starts the OS has no means of completing. This function, when called from such a test, gracefully ends the current test case and proceeds to the next test case. The particulars of this function depend on whether it is called from a simulated environment. In a simulated environment, this function uses a longjmp() call to break out of the current test case. Arguments N/A Returned values Returns 0 on success; nonzero on failure. Example void os_test_restart(void) { .... tu_restart(); } #endif","title":"tu_restart"},{"location":"os/modules/testutil/tu_restart/#tu_restart","text":"void tu_restart(void) This function is used when a system reset is necessary to proceed with testing. For example, the OS is designed to run forever once started, so a test which creates several OS tasks and then starts the OS has no means of completing. This function, when called from such a test, gracefully ends the current test case and proceeds to the next test case. The particulars of this function depend on whether it is called from a simulated environment. In a simulated environment, this function uses a longjmp() call to break out of the current test case.","title":" tu_restart "},{"location":"os/modules/testutil/tu_restart/#arguments","text":"N/A","title":"Arguments"},{"location":"os/modules/testutil/tu_restart/#returned-values","text":"Returns 0 on success; nonzero on failure.","title":"Returned values"},{"location":"os/modules/testutil/tu_restart/#example","text":"void os_test_restart(void) { .... tu_restart(); } #endif","title":"Example"},{"location":"os/tutorials/STM32F303/","text":"Blinky, your \"Hello World!\", on STM32F303 Discovery Objective Learn how to use packages from a default application repository of Mynewt to build your first Hello World application (Blinky) on a target board. Once built using the newt tool, this application will blink the LED lights on the target board. Create a project with a simple app that blinks an LED on the stmf303 discovery board. In the process import some external libraries into your project. Download the application to the target and watch it blink! What you need Discovery kit with STM32F303VC MCU Laptop running Mac OSX. It is assumed you have already installed newt tool. It is assumed you already installed native tools as described here Also, we assume that you're familiar with UNIX shells. Let's gets started! Create a project Create a new project to hold your work. For a deeper understanding, you can read about project creation in Get Started -- Creating Your First Project or just follow the commands below. If you've already created a project from another tutorial, you can re-use that project. $ mkdir ~/dev $ cd ~/dev $ newt new myproj Downloading project skeleton from apache/incubator-mynewt-blinky... Installing skeleton in myproj... Project myproj successfully created. $ cd myproj Note: Don't forget to change into the myproj directory. Import External STM32F3 Library support The STM32F303 support for Mynewt lives in an external repository. It's necessary to add another repository to the project. To do this, edit the file project.yml in the root directory of your project myproj This requires two changes to this file. You must define the properties of the external repository that you want to add You must include the repository in your project. Edit the file project.yml with your favorite editor and add the following repository details in the file (after the core repository). This gives newt the information to contact the repository and extract its contents. In this case, the repository is on github in the runtimeco collection. Its name is mynewt-stm32f3 and we will accept any version up to the latest. You can look at the contents here . repository.mynewt_stm32f3: type: github vers: 0-latest user: runtimeco repo: mynewt_stm32f3 In the same file, add the following highlighted line to the project.repositories variable. This tells newt to download the repository contents into your project. project.repositories: - apache-mynewt-core - mynewt_stm32f3 Install dependencies Now you can install this into the project using: $ newt install -v Downloading repository description for apache-mynewt-core... success! ... apache-mynewt-core successfully installed version 0.9.1-none ... Downloading repository description for mynewt_stm32f3... success! Downloading repository mynewt_stm32f3 ... Resolving deltas: 100% (65/65), done. Checking connectivity... done. mynewt_stm32f3 successfully installed version 0.9.0-none Create targets Create two targets to build using the stmf3 board support package and the app blinky example from mynewt. The output of these commands are not shown here for brevity. The first target is the application image itself. The second target is the bootloader which allows you to upgrade your mynewt applications. $ newt target create stmf3_blinky $ newt target set stmf3_blinky build_profile=optimized $ newt target set stmf3_blinky bsp=@mynewt_stm32f3/hw/bsp/stm32f3discovery $ newt target set stmf3_blinky app=apps/blinky $ newt target create stmf3_boot $ newt target set stmf3_boot app=@apache-mynewt-core/apps/boot $ newt target set stmf3_boot bsp=@mynewt_stm32f3/hw/bsp/stm32f3discovery $ newt target set stmf3_boot build_profile=optimized $ newt target show targets/stmf3_blinky app=apps/blinky bsp=@mynewt_stm32f3/hw/bsp/stm32f3discovery build_profile=optimized targets/stmf3_boot app=apps/boot bsp=@mynewt_stm32f3/hw/bsp/stm32f3discovery build_profile=optimized Build the target executables To build the images, use the newt build command below. $ newt build stmf3_blinky ... Archiving stm32f3discovery.a Linking blinky.elf App successfully built: ~/dev/myproj/bin/stmf3_blinky/apps/blinky/blinky.elf $ newt build stmf3_boot Compiling log_shell.c Archiving log.a Linking boot.elf App successfully built: ~/dev/myproj/bin/stmf3_boot/apps/boot/boot.elf Sign and create the blinky application image You must sign and version your application image to download it using newt. Use the newt create-image command to perform this action. Here we assign this image an arbitrary version 1.2.3 . $ newt create-image stmf3_blinky 1.2.3 App image successfully generated: ~/dev/myproj/bin/stmf3_blinky/apps/blinky/blinky.img Build manifest:~/dev/myproj/bin/stmf3_blinky/apps/blinky/manifest.json Configure the hardware The STM32F3DISCOVERY board includes an ST-LINK/V2 embedded debug tool interface that will be used to program/debug the board. To program the MCU on the board, simply plug in the two jumpers on CN4, as shown in the picture in red. If you want to learn more about the board you will find the User Manual at http://www.st.com/st-web-ui/static/active/jp/resource/technical/document/user_manual/DM00063382.pdf Just plug the USB cable into the USB ST-LINK port and it should power on and be ready to dowload to. Download the Images Use the newt load command to download the images to the target board. $ newt -v load stmf3_boot $ newt -v load stmf3_blinky Watch the LED blink Congratulations! You have built, downloaded, and run your first application using mynewt for the stm32f3 discovery board. One of the LEDs on the LED wheel should be blinking at 1 Hz. Want more? Want to make your board do something a little more exciting with the LEDs? Then try making the modifications to the Blinky app to make it a pin-wheel app and you can light all the LEDs in a pin-wheel fashion. We have more fun tutorials for you to get your hands dirty. Be bold and try other Blinky-like tutorials or try enabling additional functionality such as remote comms on the current board. If you see anything missing or want to send us feedback, please do so by signing up for appropriate mailing lists on our Community Page . Keep on hacking and blinking!","title":"STM32F303"},{"location":"os/tutorials/STM32F303/#blinky-your-hello-world-on-stm32f303-discovery","text":"","title":"Blinky, your \"Hello World!\", on STM32F303 Discovery"},{"location":"os/tutorials/STM32F303/#objective","text":"Learn how to use packages from a default application repository of Mynewt to build your first Hello World application (Blinky) on a target board. Once built using the newt tool, this application will blink the LED lights on the target board. Create a project with a simple app that blinks an LED on the stmf303 discovery board. In the process import some external libraries into your project. Download the application to the target and watch it blink!","title":"Objective"},{"location":"os/tutorials/STM32F303/#what-you-need","text":"Discovery kit with STM32F303VC MCU Laptop running Mac OSX. It is assumed you have already installed newt tool. It is assumed you already installed native tools as described here Also, we assume that you're familiar with UNIX shells. Let's gets started!","title":"What you need"},{"location":"os/tutorials/STM32F303/#create-a-project","text":"Create a new project to hold your work. For a deeper understanding, you can read about project creation in Get Started -- Creating Your First Project or just follow the commands below. If you've already created a project from another tutorial, you can re-use that project. $ mkdir ~/dev $ cd ~/dev $ newt new myproj Downloading project skeleton from apache/incubator-mynewt-blinky... Installing skeleton in myproj... Project myproj successfully created. $ cd myproj Note: Don't forget to change into the myproj directory.","title":"Create a project"},{"location":"os/tutorials/STM32F303/#import-external-stm32f3-library-support","text":"The STM32F303 support for Mynewt lives in an external repository. It's necessary to add another repository to the project. To do this, edit the file project.yml in the root directory of your project myproj This requires two changes to this file. You must define the properties of the external repository that you want to add You must include the repository in your project. Edit the file project.yml with your favorite editor and add the following repository details in the file (after the core repository). This gives newt the information to contact the repository and extract its contents. In this case, the repository is on github in the runtimeco collection. Its name is mynewt-stm32f3 and we will accept any version up to the latest. You can look at the contents here . repository.mynewt_stm32f3: type: github vers: 0-latest user: runtimeco repo: mynewt_stm32f3 In the same file, add the following highlighted line to the project.repositories variable. This tells newt to download the repository contents into your project. project.repositories: - apache-mynewt-core - mynewt_stm32f3","title":"Import External STM32F3 Library support"},{"location":"os/tutorials/STM32F303/#install-dependencies","text":"Now you can install this into the project using: $ newt install -v Downloading repository description for apache-mynewt-core... success! ... apache-mynewt-core successfully installed version 0.9.1-none ... Downloading repository description for mynewt_stm32f3... success! Downloading repository mynewt_stm32f3 ... Resolving deltas: 100% (65/65), done. Checking connectivity... done. mynewt_stm32f3 successfully installed version 0.9.0-none","title":"Install dependencies"},{"location":"os/tutorials/STM32F303/#create-targets","text":"Create two targets to build using the stmf3 board support package and the app blinky example from mynewt. The output of these commands are not shown here for brevity. The first target is the application image itself. The second target is the bootloader which allows you to upgrade your mynewt applications. $ newt target create stmf3_blinky $ newt target set stmf3_blinky build_profile=optimized $ newt target set stmf3_blinky bsp=@mynewt_stm32f3/hw/bsp/stm32f3discovery $ newt target set stmf3_blinky app=apps/blinky $ newt target create stmf3_boot $ newt target set stmf3_boot app=@apache-mynewt-core/apps/boot $ newt target set stmf3_boot bsp=@mynewt_stm32f3/hw/bsp/stm32f3discovery $ newt target set stmf3_boot build_profile=optimized $ newt target show targets/stmf3_blinky app=apps/blinky bsp=@mynewt_stm32f3/hw/bsp/stm32f3discovery build_profile=optimized targets/stmf3_boot app=apps/boot bsp=@mynewt_stm32f3/hw/bsp/stm32f3discovery build_profile=optimized","title":"Create targets"},{"location":"os/tutorials/STM32F303/#build-the-target-executables","text":"To build the images, use the newt build command below. $ newt build stmf3_blinky ... Archiving stm32f3discovery.a Linking blinky.elf App successfully built: ~/dev/myproj/bin/stmf3_blinky/apps/blinky/blinky.elf $ newt build stmf3_boot Compiling log_shell.c Archiving log.a Linking boot.elf App successfully built: ~/dev/myproj/bin/stmf3_boot/apps/boot/boot.elf","title":"Build the target executables"},{"location":"os/tutorials/STM32F303/#sign-and-create-the-blinky-application-image","text":"You must sign and version your application image to download it using newt. Use the newt create-image command to perform this action. Here we assign this image an arbitrary version 1.2.3 . $ newt create-image stmf3_blinky 1.2.3 App image successfully generated: ~/dev/myproj/bin/stmf3_blinky/apps/blinky/blinky.img Build manifest:~/dev/myproj/bin/stmf3_blinky/apps/blinky/manifest.json","title":"Sign and create the blinky application image"},{"location":"os/tutorials/STM32F303/#configure-the-hardware","text":"The STM32F3DISCOVERY board includes an ST-LINK/V2 embedded debug tool interface that will be used to program/debug the board. To program the MCU on the board, simply plug in the two jumpers on CN4, as shown in the picture in red. If you want to learn more about the board you will find the User Manual at http://www.st.com/st-web-ui/static/active/jp/resource/technical/document/user_manual/DM00063382.pdf Just plug the USB cable into the USB ST-LINK port and it should power on and be ready to dowload to.","title":"Configure the hardware"},{"location":"os/tutorials/STM32F303/#download-the-images","text":"Use the newt load command to download the images to the target board. $ newt -v load stmf3_boot $ newt -v load stmf3_blinky","title":"Download the Images"},{"location":"os/tutorials/STM32F303/#watch-the-led-blink","text":"Congratulations! You have built, downloaded, and run your first application using mynewt for the stm32f3 discovery board. One of the LEDs on the LED wheel should be blinking at 1 Hz.","title":"Watch the LED blink"},{"location":"os/tutorials/STM32F303/#want-more","text":"Want to make your board do something a little more exciting with the LEDs? Then try making the modifications to the Blinky app to make it a pin-wheel app and you can light all the LEDs in a pin-wheel fashion. We have more fun tutorials for you to get your hands dirty. Be bold and try other Blinky-like tutorials or try enabling additional functionality such as remote comms on the current board. If you see anything missing or want to send us feedback, please do so by signing up for appropriate mailing lists on our Community Page . Keep on hacking and blinking!","title":"Want more?"},{"location":"os/tutorials/add_newtmgr/","text":"Enabling Newt Manager in Your Application In order for your application to communicate with the newtmgr tool and process Newt Manager commands, you must enable Newt Manager device management and the support to process Newt Manager commands in your application. This tutorial explains how to add the support to your application. This tutorial assumes that you have read the Device Management with Newt Manager guide and are familiar with the newtmgr and oicmgr frameworks and all the options that are available to customize your application. This tutorial shows you how to configure your application to: Use the newtmgr framework. Use serial transport to communicate with the newtmgr tool. Support all Newt Manager commands. See Other Configuration Options on how to customize your application. Prerequisites Ensure that you have met the following prerequisites before continuing with this tutorial: Have Internet connectivity to fetch remote Mynewt components. Have a cable to establish a serial USB connection between the board and the laptop. Install the newt tool and toolchains (See Basic Setup ). Install the newtmgr tool . Use an Existing Project We assume that you have worked through at least some of the other tutorials and have an existing project. In this example, we modify the ble_tiny project to enable Newt Manager support. We call our application myble . You can create the application using any name you choose. Modify Package Dependencies and Configurations Add the following packages to the pkg.deps parameter in your target or application pkg.yml file: pkg.deps: - mgmt/newtmgr - mgmt/newtmgr/transport/nmgr_shell - mgmt/imgmgr - sys/log/full - sys/stats/full - sys/config - test/crash_test - test/runtest Each package provides the following Newt Manager functionality: mgmt/newtmgr : Supports the newtmgr framework and the Newt Manager echo , taskstats mpstats , datetime , and reset commands. mgmt/newtmgr/transport/nmgr_shell : Supports serial transport. mgmt/imgmgr : Supports the newtmgr image command sys/log/full : Supports the newtmgr log command. sys/stats/full : Supports the newtmgr stat command. sys/config : Supports the newtmgr config command. test/crash_test : Supports the newtmgr crash command. test/runtest : Supports the newt run command. Add the following configuration setting values to the syscfg.vals parameter in the target or application syscfg.yml file: syscfg.vals: LOG_NEWTMGR: 1 STATS_NEWTMGR: 1 CONFIG_NEWTMGR: 1 CRASH_TEST_NEWTMGR: 1 RUNTEST_NEWTMGR: 1 SHELL_TASK: 1 The first five configuration settings enable support for the Newt Manager log , stat , config , crash , and run commands. The SHELL_TASK setting enables the shell for serial transport. Note that you may need to override additional configuration settings that are specific to each package to customize the package functionality. Modify the Source By default, the mgmt package uses the Mynewt default event queue to receive request events from the newtmgr tool. These events are processed in the context of the application main task. You can specify a different event queue for the package to use. If you choose to use a dedicated event queue, you must create a task to process events from this event queue. The mgmt package executes and handles newtmgr request events in the context of this task. The mgmt package exports the mgmt_evq_set() function that allows you to specify an event queue. This example uses the Mynewt default event queue and you do not need to modify your application source. If you choose to use a different event queue, see Events and Event Queues for details on how to initialize an event queue and create a task to process the events. You will also need to modify your main.c to add the call to the mgmt_evq_set() function as follows: Add the mgmt/mgmt.h header file: #include <mgmt/mgmt.h> Add the call to specify the event queue. In the main() function, scroll down to the while (1) loop and add the following statement above the loop: mgmt_evq_set(&my_eventq) where my_eventq is an event queue that you have initialized. Build the Targets Build the two targets as follows: $ newt build nrf52_boot <snip> App successfully built: ./bin/nrf52_boot/apps/boot/boot.elf $ newt build myble Compiling hci_common.c Compiling util.c Archiving nimble.a Compiling os.c <snip> Create the Application Image Generate a signed application image for the myble target. You can use any version number you choose. $ newt create-image myble 1.0.0 App image successfully generated: ./bin/makerbeacon/apps/bletiny/bletiny.img Build manifest: ./bin/makerbeacon/apps/bletiny/manifest.json Load the Image Ensure the USB connector is in place and the power LED on the board is lit. Turn the power switch on your board off, then back on to reset the board after loading the image. $ newt load nrf52_boot $ newt load myble Set Up a Connection Profile The newtmgr tool requires a connection profile in order to connect to your board. If you have not done so, follow the instructions for setting up your connection profile. Communicate with Your Application Once you have a connection profile set up, you can connect to your device with newtmgr -c myconn <command> to run commands in your application. Issue the echo command to ensure that your application is communicating with the newtmgr tool: # newtmgr -c myconn echo hello hello Test your application to ensure that it can process a Newt Manager command that is supported by a different package. Issue the stat command to see the BLE stats. newtmgr -c myconn stat ble_att Return Code = 0 Stats Name: ble_att prep_write_req_tx: 0 indicate_req_tx: 0 write_rsp_tx: 0 find_info_req_tx: 0 read_rsp_rx: 0 read_group_type_rsp_tx: 0 indicate_req_rx: 0 find_type_value_rsp_tx: 0 ... read_req_rx: 0 read_type_req_rx: 0 notify_req_tx: 0 mtu_rsp_tx: 0 find_type_value_req_rx: 0 read_blob_rsp_rx: 0 read_group_type_req_tx: 0 exec_write_req_tx: 0 Your application is now able to communicate with the newtmgr tool. Other Configuration Options This section explains how to customize your application to use other Newt Manager protocol options. Newtmgr Framework Transport Protocol Options The newtmgr framework currently supports BLE and serial transport protocols. To configure the transport protocols that are supported, modify the pkg.yml and syscfg.yml files as follows: Add the mgmt/newtmgr/transport/ble package to the pkg.deps parameter to enable BLE transport. Add the mgmt/newtmgr/transport/nmgr_shell package to the pkg.deps parameter, and add SHELL_TASK: 1 to the syscfg.vals parameter to enable serial transport when your application also uses the Shell . Add the mgmt/newtmgr/transport/nmgr_uart package to the pkg.deps parameter to enable serial transport over a UART port. You can use this package instead of the nmgr_shell package when your application does not use the Shell or you want to use a dedicated UART port to communicate with newtmgr. You can change the NMGR_UART and NMGR_URART_SPEED sysconfig values to specify a different port. Oicmgr Framework Options To use the oicmgr framework instead of the newtmgr framework, modify the pkg.yml and syscfg.yml files as follows: Add the mgmt/oicmgr package (instead of the mgmt/newtmgr and mgmt/newtmgr/transport packages as described previously) to the pkg.deps parameter. Add OC_SERVER: 1 to the syscfg.vals parameter. Oicmgr supports the IP, serial, and BLE transport protocols. To configure the transport protocols that are supported, set the configuration setting values in the syscfg.vals parameter as follows: Add OC_TRANSPORT_IP: 1 to enable IP transport. Add OC_TRANSPORT_GATT: 1 to enable BLE transport. Add OC_TRANSPORT_SERIAL: 1 and SHELL_TASK: 1 to enable serial transport. Customize the Newt Manager Commands that Your Application Supports We recommend that you only enable support for the Newt Manager commands that your application uses to reduce your application code size. To configure the commands that are supported, set the configuration setting values in the syscfg.vals parameter as follows: Add LOG_NEWTMGR: 1 to enable support for the newtmgr log command. Add STATS_NEWTMGR: 1 to enable support for the newtmgr stat command. Add CONFIG_NEWTMGR: 1 to enable support for the newtmgr config command. Add CRASH_TEST_NEWTMGR: 1 to enable support for the newtmgr crash command. Add RUNTEST_NEWTMGR: 1 to enable support for the newtmgr crash command. Notes: When you enable Newt Manager support, using either the newtmgr or oicmgr framework, your application automatically supports the Newt Manager echo , taskstats , mpstats , datetime , and reset commands. These commands cannot be configured individually. The mgmt/imgmgr package does not provide a configuration setting to enable or disable support for the newtmgr image command. Do not specify the package in the pkg.deps parameter if your device has limited flash memory and cannot support Over-The-Air (OTA) firmware upgrades.","title":"Enable Newt Manager in any app"},{"location":"os/tutorials/add_newtmgr/#enabling-newt-manager-in-your-application","text":"In order for your application to communicate with the newtmgr tool and process Newt Manager commands, you must enable Newt Manager device management and the support to process Newt Manager commands in your application. This tutorial explains how to add the support to your application. This tutorial assumes that you have read the Device Management with Newt Manager guide and are familiar with the newtmgr and oicmgr frameworks and all the options that are available to customize your application. This tutorial shows you how to configure your application to: Use the newtmgr framework. Use serial transport to communicate with the newtmgr tool. Support all Newt Manager commands. See Other Configuration Options on how to customize your application.","title":"Enabling Newt Manager in Your Application"},{"location":"os/tutorials/add_newtmgr/#prerequisites","text":"Ensure that you have met the following prerequisites before continuing with this tutorial: Have Internet connectivity to fetch remote Mynewt components. Have a cable to establish a serial USB connection between the board and the laptop. Install the newt tool and toolchains (See Basic Setup ). Install the newtmgr tool .","title":"Prerequisites"},{"location":"os/tutorials/add_newtmgr/#use-an-existing-project","text":"We assume that you have worked through at least some of the other tutorials and have an existing project. In this example, we modify the ble_tiny project to enable Newt Manager support. We call our application myble . You can create the application using any name you choose.","title":"Use an Existing Project"},{"location":"os/tutorials/add_newtmgr/#modify-package-dependencies-and-configurations","text":"Add the following packages to the pkg.deps parameter in your target or application pkg.yml file: pkg.deps: - mgmt/newtmgr - mgmt/newtmgr/transport/nmgr_shell - mgmt/imgmgr - sys/log/full - sys/stats/full - sys/config - test/crash_test - test/runtest Each package provides the following Newt Manager functionality: mgmt/newtmgr : Supports the newtmgr framework and the Newt Manager echo , taskstats mpstats , datetime , and reset commands. mgmt/newtmgr/transport/nmgr_shell : Supports serial transport. mgmt/imgmgr : Supports the newtmgr image command sys/log/full : Supports the newtmgr log command. sys/stats/full : Supports the newtmgr stat command. sys/config : Supports the newtmgr config command. test/crash_test : Supports the newtmgr crash command. test/runtest : Supports the newt run command. Add the following configuration setting values to the syscfg.vals parameter in the target or application syscfg.yml file: syscfg.vals: LOG_NEWTMGR: 1 STATS_NEWTMGR: 1 CONFIG_NEWTMGR: 1 CRASH_TEST_NEWTMGR: 1 RUNTEST_NEWTMGR: 1 SHELL_TASK: 1 The first five configuration settings enable support for the Newt Manager log , stat , config , crash , and run commands. The SHELL_TASK setting enables the shell for serial transport. Note that you may need to override additional configuration settings that are specific to each package to customize the package functionality.","title":"Modify Package Dependencies and Configurations"},{"location":"os/tutorials/add_newtmgr/#modify-the-source","text":"By default, the mgmt package uses the Mynewt default event queue to receive request events from the newtmgr tool. These events are processed in the context of the application main task. You can specify a different event queue for the package to use. If you choose to use a dedicated event queue, you must create a task to process events from this event queue. The mgmt package executes and handles newtmgr request events in the context of this task. The mgmt package exports the mgmt_evq_set() function that allows you to specify an event queue. This example uses the Mynewt default event queue and you do not need to modify your application source. If you choose to use a different event queue, see Events and Event Queues for details on how to initialize an event queue and create a task to process the events. You will also need to modify your main.c to add the call to the mgmt_evq_set() function as follows: Add the mgmt/mgmt.h header file: #include <mgmt/mgmt.h> Add the call to specify the event queue. In the main() function, scroll down to the while (1) loop and add the following statement above the loop: mgmt_evq_set(&my_eventq) where my_eventq is an event queue that you have initialized.","title":"Modify the Source"},{"location":"os/tutorials/add_newtmgr/#build-the-targets","text":"Build the two targets as follows: $ newt build nrf52_boot <snip> App successfully built: ./bin/nrf52_boot/apps/boot/boot.elf $ newt build myble Compiling hci_common.c Compiling util.c Archiving nimble.a Compiling os.c <snip>","title":"Build the Targets"},{"location":"os/tutorials/add_newtmgr/#create-the-application-image","text":"Generate a signed application image for the myble target. You can use any version number you choose. $ newt create-image myble 1.0.0 App image successfully generated: ./bin/makerbeacon/apps/bletiny/bletiny.img Build manifest: ./bin/makerbeacon/apps/bletiny/manifest.json","title":"Create the Application Image"},{"location":"os/tutorials/add_newtmgr/#load-the-image","text":"Ensure the USB connector is in place and the power LED on the board is lit. Turn the power switch on your board off, then back on to reset the board after loading the image. $ newt load nrf52_boot $ newt load myble","title":"Load the Image"},{"location":"os/tutorials/add_newtmgr/#set-up-a-connection-profile","text":"The newtmgr tool requires a connection profile in order to connect to your board. If you have not done so, follow the instructions for setting up your connection profile.","title":"Set Up a Connection Profile"},{"location":"os/tutorials/add_newtmgr/#communicate-with-your-application","text":"Once you have a connection profile set up, you can connect to your device with newtmgr -c myconn <command> to run commands in your application. Issue the echo command to ensure that your application is communicating with the newtmgr tool: # newtmgr -c myconn echo hello hello Test your application to ensure that it can process a Newt Manager command that is supported by a different package. Issue the stat command to see the BLE stats. newtmgr -c myconn stat ble_att Return Code = 0 Stats Name: ble_att prep_write_req_tx: 0 indicate_req_tx: 0 write_rsp_tx: 0 find_info_req_tx: 0 read_rsp_rx: 0 read_group_type_rsp_tx: 0 indicate_req_rx: 0 find_type_value_rsp_tx: 0 ... read_req_rx: 0 read_type_req_rx: 0 notify_req_tx: 0 mtu_rsp_tx: 0 find_type_value_req_rx: 0 read_blob_rsp_rx: 0 read_group_type_req_tx: 0 exec_write_req_tx: 0 Your application is now able to communicate with the newtmgr tool.","title":"Communicate with Your Application"},{"location":"os/tutorials/add_newtmgr/#other-configuration-options","text":"This section explains how to customize your application to use other Newt Manager protocol options.","title":"Other Configuration Options"},{"location":"os/tutorials/add_newtmgr/#newtmgr-framework-transport-protocol-options","text":"The newtmgr framework currently supports BLE and serial transport protocols. To configure the transport protocols that are supported, modify the pkg.yml and syscfg.yml files as follows: Add the mgmt/newtmgr/transport/ble package to the pkg.deps parameter to enable BLE transport. Add the mgmt/newtmgr/transport/nmgr_shell package to the pkg.deps parameter, and add SHELL_TASK: 1 to the syscfg.vals parameter to enable serial transport when your application also uses the Shell . Add the mgmt/newtmgr/transport/nmgr_uart package to the pkg.deps parameter to enable serial transport over a UART port. You can use this package instead of the nmgr_shell package when your application does not use the Shell or you want to use a dedicated UART port to communicate with newtmgr. You can change the NMGR_UART and NMGR_URART_SPEED sysconfig values to specify a different port.","title":"Newtmgr Framework Transport Protocol Options"},{"location":"os/tutorials/add_newtmgr/#oicmgr-framework-options","text":"To use the oicmgr framework instead of the newtmgr framework, modify the pkg.yml and syscfg.yml files as follows: Add the mgmt/oicmgr package (instead of the mgmt/newtmgr and mgmt/newtmgr/transport packages as described previously) to the pkg.deps parameter. Add OC_SERVER: 1 to the syscfg.vals parameter. Oicmgr supports the IP, serial, and BLE transport protocols. To configure the transport protocols that are supported, set the configuration setting values in the syscfg.vals parameter as follows: Add OC_TRANSPORT_IP: 1 to enable IP transport. Add OC_TRANSPORT_GATT: 1 to enable BLE transport. Add OC_TRANSPORT_SERIAL: 1 and SHELL_TASK: 1 to enable serial transport.","title":"Oicmgr Framework Options"},{"location":"os/tutorials/add_newtmgr/#customize-the-newt-manager-commands-that-your-application-supports","text":"We recommend that you only enable support for the Newt Manager commands that your application uses to reduce your application code size. To configure the commands that are supported, set the configuration setting values in the syscfg.vals parameter as follows: Add LOG_NEWTMGR: 1 to enable support for the newtmgr log command. Add STATS_NEWTMGR: 1 to enable support for the newtmgr stat command. Add CONFIG_NEWTMGR: 1 to enable support for the newtmgr config command. Add CRASH_TEST_NEWTMGR: 1 to enable support for the newtmgr crash command. Add RUNTEST_NEWTMGR: 1 to enable support for the newtmgr crash command. Notes: When you enable Newt Manager support, using either the newtmgr or oicmgr framework, your application automatically supports the Newt Manager echo , taskstats , mpstats , datetime , and reset commands. These commands cannot be configured individually. The mgmt/imgmgr package does not provide a configuration setting to enable or disable support for the newtmgr image command. Do not specify the package in the pkg.deps parameter if your device has limited flash memory and cannot support Over-The-Air (OTA) firmware upgrades.","title":"Customize the Newt Manager Commands that Your Application Supports"},{"location":"os/tutorials/add_shell/","text":"Enabling The Console and Shell in a project This tutorial explains how to add the Console and Shell task to a project so that you can interact with your project over a serial line connection. Prerequisites Ensure that you have met the following prerequisites before continuing with this tutorial: Have Internet connectivity to fetch remote Mynewt components. Have a cable to establish a serial USB connection between the board and the laptop Install the newt tool and toolchains (See Basic Setup ). Install the Segger JLINK package to load your project on the board. Use an existing project Since all we're doing is adding the shell and console capability to a project, we assume that you have worked through at least some of the other tutorials, and have an existing project. For this example, we'll be modifying the ble_tiny project to enable the shell and console connectivity. We'll be calling our app myble as in that project as well. Feel free to use whatever project you'd like though. Modify the Dependencies and Configuration The first thing you'll need to add is a few new dependencies for your app. To add shell support to your app make sure the following pkg.deps are defined in your target's pkg.yml file: pkg.deps: - \"@apache-mynewt-core/sys/console/full\" - \"@apache-mynewt-core/sys/shell\" - \"@apache-mynewt-core/sys/sysinit\" This lets the newt system know that it needs to pull in the code for the console and the shell. Now we'll need to modify the settings for the app to turn on the shell, etc. by modifying the syscfg.yml file for your target. (Remember, these files are in the targets/ directory.) If there isn't a syscfg.yml file in your target's directory, you will need to create one. # Package: apps/bletiny syscfg.vals: # Enable the shell task. SHELL_TASK: 1 # Enable Console OS Ticks CONSOLE_TICKS: 1 # Enable Console Prompt CONSOLE_PROMPT: 1 Build targets We're not going to build the bootloader here since we are assuming that you have already built and loaded it during previous tutorials. $ newt build myble Archiving cbmem.a Compiling crc16.c Compiling crc8.c Archiving crc.a Compiling mem.c Archiving mem.a Linking ~/dev/myproj/bin/targets/myble/app/apps/bletiny/bletiny.elf Target successfully built: targets/myble Create the app image Generate a signed application image for the myble target. The version number is arbitrary. $ newt create-image myble 1.0.0 App image succesfully generated: ~/dev/myproj/bin/targets/myble/app/apps/bletiny/bletiny.img Load the image Make sure the USB connector is in place and the power LED on the board is lit. Use the Power ON/OFF switch to reset the board after loading the image. $ newt load myble Set up Serial connection You'll need a Serial connection to see the output of your program. You can reference the Serial Port Setup Tutorial for more information on setting up your serial communications. Connecting with your app Once you have a connection set up, you can connect to your device as follows: On Mac OS and Linux platforms, you can run minicom -D /dev/tty.usbserial-<port> -b 115200 to connect to the console of your app. Note that on Linux, the format of the port name is /dev/ttyUSB<N> , where N is a number. On Windows, you can use a terminal application such as PuTTY to connect to the device. If you located your port from a MinGW terminal, the port name format is /dev/ttyS<N> , where N is a number. You must map the port name to a Windows COM port: /dev/ttyS<N> maps to COM<N+1> . For example, /dev/ttyS2 maps to COM3 . You can also use the Windows Device Manager to locate the COM port. To test and make sure that the Shell is running, first just hit : 3534: > Remember, we turned the CONSOLE_PROMPT and the CONSOLE_TICKS on earlier. You can try some commands now: 3609: > ? Commands: 8841: echo ? prompt ticks tasks mempools 8843: date b 8844: > ticks off Console Ticks off > prompt off Prompt now off. ticks on 33383: Console Ticks on 33568: prompt on 39108: Prompt now on. 39108: >","title":"Enable the OS Shell and Console"},{"location":"os/tutorials/add_shell/#enabling-the-console-and-shell-in-a-project","text":"This tutorial explains how to add the Console and Shell task to a project so that you can interact with your project over a serial line connection.","title":"Enabling The Console and Shell in a project"},{"location":"os/tutorials/add_shell/#prerequisites","text":"Ensure that you have met the following prerequisites before continuing with this tutorial: Have Internet connectivity to fetch remote Mynewt components. Have a cable to establish a serial USB connection between the board and the laptop Install the newt tool and toolchains (See Basic Setup ). Install the Segger JLINK package to load your project on the board.","title":"Prerequisites"},{"location":"os/tutorials/add_shell/#use-an-existing-project","text":"Since all we're doing is adding the shell and console capability to a project, we assume that you have worked through at least some of the other tutorials, and have an existing project. For this example, we'll be modifying the ble_tiny project to enable the shell and console connectivity. We'll be calling our app myble as in that project as well. Feel free to use whatever project you'd like though.","title":"Use an existing project"},{"location":"os/tutorials/add_shell/#modify-the-dependencies-and-configuration","text":"The first thing you'll need to add is a few new dependencies for your app. To add shell support to your app make sure the following pkg.deps are defined in your target's pkg.yml file: pkg.deps: - \"@apache-mynewt-core/sys/console/full\" - \"@apache-mynewt-core/sys/shell\" - \"@apache-mynewt-core/sys/sysinit\" This lets the newt system know that it needs to pull in the code for the console and the shell. Now we'll need to modify the settings for the app to turn on the shell, etc. by modifying the syscfg.yml file for your target. (Remember, these files are in the targets/ directory.) If there isn't a syscfg.yml file in your target's directory, you will need to create one. # Package: apps/bletiny syscfg.vals: # Enable the shell task. SHELL_TASK: 1 # Enable Console OS Ticks CONSOLE_TICKS: 1 # Enable Console Prompt CONSOLE_PROMPT: 1","title":"Modify the Dependencies and Configuration"},{"location":"os/tutorials/add_shell/#build-targets","text":"We're not going to build the bootloader here since we are assuming that you have already built and loaded it during previous tutorials. $ newt build myble Archiving cbmem.a Compiling crc16.c Compiling crc8.c Archiving crc.a Compiling mem.c Archiving mem.a Linking ~/dev/myproj/bin/targets/myble/app/apps/bletiny/bletiny.elf Target successfully built: targets/myble","title":"Build targets"},{"location":"os/tutorials/add_shell/#create-the-app-image","text":"Generate a signed application image for the myble target. The version number is arbitrary. $ newt create-image myble 1.0.0 App image succesfully generated: ~/dev/myproj/bin/targets/myble/app/apps/bletiny/bletiny.img","title":"Create the app image"},{"location":"os/tutorials/add_shell/#load-the-image","text":"Make sure the USB connector is in place and the power LED on the board is lit. Use the Power ON/OFF switch to reset the board after loading the image. $ newt load myble","title":"Load the image"},{"location":"os/tutorials/add_shell/#set-up-serial-connection","text":"You'll need a Serial connection to see the output of your program. You can reference the Serial Port Setup Tutorial for more information on setting up your serial communications.","title":"Set up Serial connection"},{"location":"os/tutorials/add_shell/#connecting-with-your-app","text":"Once you have a connection set up, you can connect to your device as follows: On Mac OS and Linux platforms, you can run minicom -D /dev/tty.usbserial-<port> -b 115200 to connect to the console of your app. Note that on Linux, the format of the port name is /dev/ttyUSB<N> , where N is a number. On Windows, you can use a terminal application such as PuTTY to connect to the device. If you located your port from a MinGW terminal, the port name format is /dev/ttyS<N> , where N is a number. You must map the port name to a Windows COM port: /dev/ttyS<N> maps to COM<N+1> . For example, /dev/ttyS2 maps to COM3 . You can also use the Windows Device Manager to locate the COM port. To test and make sure that the Shell is running, first just hit : 3534: > Remember, we turned the CONSOLE_PROMPT and the CONSOLE_TICKS on earlier. You can try some commands now: 3609: > ? Commands: 8841: echo ? prompt ticks tasks mempools 8843: date b 8844: > ticks off Console Ticks off > prompt off Prompt now off. ticks on 33383: Console Ticks on 33568: prompt on 39108: Prompt now on. 39108: >","title":"Connecting with your app"},{"location":"os/tutorials/air_quality_ble/","text":"Air quality sensor project via Bluetooth This is a follow-on project to the Basic Air Quality Sensor project; so it is assumed that you have worked through that project and have your CO 2 sensor working properly with your Arduino Primo board. So let's get started making this thing Bluetooth enabled! Add Bluetooth GATT Services Since we already built the previous demo on the bluetooth peripheral basic app most of the bluetooth plumbing has already been taken care of for us. What's left is for us to add the required GATT services for advertising the Carbon Dioxide sensor so that other devices can get those values. First, we'll define the GATT Services in apps/air_quality/src/bleprph.h . /* Sensor Data */ /* e761d2af-1c15-4fa7-af80-b5729002b340 */ static const ble_uuid128_t gatt_svr_svc_co2_uuid = BLE_UUID128_INIT ( 0x40 , 0xb3 , 0x20 , 0x90 , 0x72 , 0xb5 , 0x80 , 0xaf , 0xa7 , 0x4f , 0x15 , 0x1c , 0xaf , 0xd2 , 0x61 , 0xe7 ); #define CO2_SNS_TYPE 0xDEAD #define CO2_SNS_STRING \"SenseAir K30 CO2 Sensor\" #define CO2_SNS_VAL 0xBEAD uint16_t gatt_co2_val ; You can use any hex values you choose for the sensor type and sensor values, and you can even forget the sensor type and sensor string definitions altogether but they make the results look nice in our Bluetooth App for Mac OS X and iOS. Next we'll add those services to apps/air_quality/src/gatt_svr.c . static int gatt_svr_sns_access ( uint16_t conn_handle , uint16_t attr_handle , struct ble_gatt_access_ctxt *ctxt , void *arg ); static uint16_t gatt_co2_val_len ; Make sure it is added as primary service. static const struct ble_gatt_svc_def gatt_svr_svcs [] = { { /*** Service: Security test. */ . type = BLE_GATT_SVC_TYPE_PRIMARY , . uuid = &gatt_svr_svc_sec_test_uuid . u , . characteristics = ( struct ble_gatt_chr_def []) { { /*** Characteristic: Random number generator. */ . uuid = &gatt_svr_chr_sec_test_rand_uuid . u , . access_cb = gatt_svr_chr_access_sec_test , . flags = BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_READ_ENC , }, { /*** Characteristic: Static value. */ . uuid = &gatt_svr_chr_sec_test_static_uuid ,. u . access_cb = gatt_svr_chr_access_sec_test , . flags = BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_WRITE | BLE_GATT_CHR_F_WRITE_ENC , }, { 0 , /* No more characteristics in this service. */ } }, }, { /*** CO2 Level Notification Service. */ . type = BLE_GATT_SVC_TYPE_PRIMARY , . uuid = &gatt_svr_svc_co2_uuid . u , . characteristics = ( struct ble_gatt_chr_def []) { { . uuid = BLE_UUID16_DECLARE ( CO2_SNS_TYPE ), . access_cb = gatt_svr_sns_access , . flags = BLE_GATT_CHR_F_READ , }, { . uuid = BLE_UUID16_DECLARE ( CO2_SNS_VAL ), . access_cb = gatt_svr_sns_access , . flags = BLE_GATT_CHR_F_NOTIFY , }, { 0 , /* No more characteristics in this service. */ } }, }, { 0 , /* No more services. */ }, }; Next we need to tell the GATT Server how to handle requests for CO 2 readings : sstatic int gatt_svr_sns_access ( uint16_t conn_handle , uint16_t attr_handle , struct ble_gatt_access_ctxt *ctxt , void *arg ) { uint16_t uuid16 ; int rc ; uuid16 = ble_uuid_u16 ( ctxt->chr->uuid ); switch ( uuid16 ) { case CO2_SNS_TYPE : assert ( ctxt->op == BLE_GATT_ACCESS_OP_READ_CHR ); rc = os_mbuf_append ( ctxt->om , CO2_SNS_STRING , sizeof CO2_SNS_STRING ); BLEPRPH_LOG ( INFO , \"CO2 SENSOR TYPE READ: %s\\n\" , CO2_SNS_STRING ); return rc == 0 ? 0 : BLE_ATT_ERR_INSUFFICIENT_RES ; case CO2_SNS_VAL : if ( ctxt->op == BLE_GATT_ACCESS_OP_WRITE_CHR ) { rc = gatt_svr_chr_write ( ctxt->om , 0 , sizeof gatt_co2_val , &gatt_co2_val , &gatt_co2_val_len ); return rc ; } else if ( ctxt->op == BLE_GATT_ACCESS_OP_READ_CHR ) { rc = os_mbuf_append ( ctxt->om , &gatt_co2_val , sizeof gatt_co2_val ); return rc == 0 ? 0 : BLE_ATT_ERR_INSUFFICIENT_RES ; } default : assert ( 0 ); return BLE_ATT_ERR_UNLIKELY ; } } Now it's time to go into our apps/air_quality/src/main.c and change how we read CO 2 readings and respond to requests. We'll need a task handler with an event queue for the CO 2 readings -- they were handled by the shell task in the previous tutorial but now it needs to be replaced by a different handler as shown below. /* CO2 Task settings */ #define CO2_TASK_PRIO 5 #define CO2_STACK_SIZE (OS_STACK_ALIGN(336)) struct os_eventq co2_evq ; struct os_task co2_task ; bssnz_t os_stack_t co2_stack [ CO2_STACK_SIZE ]; And of course we'll need to go to our main() and do all the standard task and event setup we normally do by adding the following. Again, remember to delete all the shell event queues and tasks. /* Initialize sensor eventq */ os_eventq_init ( &co2_evq ); /* Create the CO2 reader task. * All sensor reading operations are performed in this task. */ os_task_init ( &co2_task , \"sensor\" , co2_task_handler , NULL , CO2_TASK_PRIO , OS_WAIT_FOREVER , co2_stack , CO2_STACK_SIZE ); We'll also need to add a task handler -- since we initialized it above: /** * Event loop for the sensor task. */ static void co2_task_handler ( void *unused ) { while ( 1 ) { co2_read_event (); /* Wait 2 second */ os_time_delay ( OS_TICKS_PER_SEC * 2 ); } } And finally, we'll take care of that co2_read_event() function: int co2_read_event ( void ) { int value ; enum senseair_read_type type = SENSEAIR_CO2 ; uint16_t chr_val_handle ; int rc ; value = senseair_read ( type ); if ( value >= 0 ) { console_printf ( \"Got %d\\n\" , value ); } else { console_printf ( \"Error while reading: %d\\n\" , value ); goto err ; } gatt_co2_val = value ; rc = ble_gatts_find_chr ( &gatt_svr_svc_co2_uuid . u , BLE_UUID16_DECLARE ( CO2_SNS_VAL ), NULL , &chr_val_handle ); assert ( rc == 0 ); ble_gatts_chr_updated ( chr_val_handle ); return ( 0 ); err : return ( rc ); } You'll notice that it looks eeirily similar to a portion of the shell event we created earlier. This one simply reads and updates the CO 2 value and sends that over BLE to any connected clients instead. We can now build, create-image and load the app onto our Arduino Primo board, and then connect and see the updated values! The image below shows the results using MyNewt Sensor Reader, a Mac OS X app developed for connecting to MyNewt devices over Bluetooth but you can also use LightBlue or any other application that can connect to, and read, Bluetooth data. Congratulations!!","title":"BLE-enabled Air Quality Sensor"},{"location":"os/tutorials/air_quality_ble/#air-quality-sensor-project-via-bluetooth","text":"This is a follow-on project to the Basic Air Quality Sensor project; so it is assumed that you have worked through that project and have your CO 2 sensor working properly with your Arduino Primo board. So let's get started making this thing Bluetooth enabled!","title":"Air quality sensor project via Bluetooth"},{"location":"os/tutorials/air_quality_ble/#add-bluetooth-gatt-services","text":"Since we already built the previous demo on the bluetooth peripheral basic app most of the bluetooth plumbing has already been taken care of for us. What's left is for us to add the required GATT services for advertising the Carbon Dioxide sensor so that other devices can get those values. First, we'll define the GATT Services in apps/air_quality/src/bleprph.h . /* Sensor Data */ /* e761d2af-1c15-4fa7-af80-b5729002b340 */ static const ble_uuid128_t gatt_svr_svc_co2_uuid = BLE_UUID128_INIT ( 0x40 , 0xb3 , 0x20 , 0x90 , 0x72 , 0xb5 , 0x80 , 0xaf , 0xa7 , 0x4f , 0x15 , 0x1c , 0xaf , 0xd2 , 0x61 , 0xe7 ); #define CO2_SNS_TYPE 0xDEAD #define CO2_SNS_STRING \"SenseAir K30 CO2 Sensor\" #define CO2_SNS_VAL 0xBEAD uint16_t gatt_co2_val ; You can use any hex values you choose for the sensor type and sensor values, and you can even forget the sensor type and sensor string definitions altogether but they make the results look nice in our Bluetooth App for Mac OS X and iOS. Next we'll add those services to apps/air_quality/src/gatt_svr.c . static int gatt_svr_sns_access ( uint16_t conn_handle , uint16_t attr_handle , struct ble_gatt_access_ctxt *ctxt , void *arg ); static uint16_t gatt_co2_val_len ; Make sure it is added as primary service. static const struct ble_gatt_svc_def gatt_svr_svcs [] = { { /*** Service: Security test. */ . type = BLE_GATT_SVC_TYPE_PRIMARY , . uuid = &gatt_svr_svc_sec_test_uuid . u , . characteristics = ( struct ble_gatt_chr_def []) { { /*** Characteristic: Random number generator. */ . uuid = &gatt_svr_chr_sec_test_rand_uuid . u , . access_cb = gatt_svr_chr_access_sec_test , . flags = BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_READ_ENC , }, { /*** Characteristic: Static value. */ . uuid = &gatt_svr_chr_sec_test_static_uuid ,. u . access_cb = gatt_svr_chr_access_sec_test , . flags = BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_WRITE | BLE_GATT_CHR_F_WRITE_ENC , }, { 0 , /* No more characteristics in this service. */ } }, }, { /*** CO2 Level Notification Service. */ . type = BLE_GATT_SVC_TYPE_PRIMARY , . uuid = &gatt_svr_svc_co2_uuid . u , . characteristics = ( struct ble_gatt_chr_def []) { { . uuid = BLE_UUID16_DECLARE ( CO2_SNS_TYPE ), . access_cb = gatt_svr_sns_access , . flags = BLE_GATT_CHR_F_READ , }, { . uuid = BLE_UUID16_DECLARE ( CO2_SNS_VAL ), . access_cb = gatt_svr_sns_access , . flags = BLE_GATT_CHR_F_NOTIFY , }, { 0 , /* No more characteristics in this service. */ } }, }, { 0 , /* No more services. */ }, }; Next we need to tell the GATT Server how to handle requests for CO 2 readings : sstatic int gatt_svr_sns_access ( uint16_t conn_handle , uint16_t attr_handle , struct ble_gatt_access_ctxt *ctxt , void *arg ) { uint16_t uuid16 ; int rc ; uuid16 = ble_uuid_u16 ( ctxt->chr->uuid ); switch ( uuid16 ) { case CO2_SNS_TYPE : assert ( ctxt->op == BLE_GATT_ACCESS_OP_READ_CHR ); rc = os_mbuf_append ( ctxt->om , CO2_SNS_STRING , sizeof CO2_SNS_STRING ); BLEPRPH_LOG ( INFO , \"CO2 SENSOR TYPE READ: %s\\n\" , CO2_SNS_STRING ); return rc == 0 ? 0 : BLE_ATT_ERR_INSUFFICIENT_RES ; case CO2_SNS_VAL : if ( ctxt->op == BLE_GATT_ACCESS_OP_WRITE_CHR ) { rc = gatt_svr_chr_write ( ctxt->om , 0 , sizeof gatt_co2_val , &gatt_co2_val , &gatt_co2_val_len ); return rc ; } else if ( ctxt->op == BLE_GATT_ACCESS_OP_READ_CHR ) { rc = os_mbuf_append ( ctxt->om , &gatt_co2_val , sizeof gatt_co2_val ); return rc == 0 ? 0 : BLE_ATT_ERR_INSUFFICIENT_RES ; } default : assert ( 0 ); return BLE_ATT_ERR_UNLIKELY ; } } Now it's time to go into our apps/air_quality/src/main.c and change how we read CO 2 readings and respond to requests. We'll need a task handler with an event queue for the CO 2 readings -- they were handled by the shell task in the previous tutorial but now it needs to be replaced by a different handler as shown below. /* CO2 Task settings */ #define CO2_TASK_PRIO 5 #define CO2_STACK_SIZE (OS_STACK_ALIGN(336)) struct os_eventq co2_evq ; struct os_task co2_task ; bssnz_t os_stack_t co2_stack [ CO2_STACK_SIZE ]; And of course we'll need to go to our main() and do all the standard task and event setup we normally do by adding the following. Again, remember to delete all the shell event queues and tasks. /* Initialize sensor eventq */ os_eventq_init ( &co2_evq ); /* Create the CO2 reader task. * All sensor reading operations are performed in this task. */ os_task_init ( &co2_task , \"sensor\" , co2_task_handler , NULL , CO2_TASK_PRIO , OS_WAIT_FOREVER , co2_stack , CO2_STACK_SIZE ); We'll also need to add a task handler -- since we initialized it above: /** * Event loop for the sensor task. */ static void co2_task_handler ( void *unused ) { while ( 1 ) { co2_read_event (); /* Wait 2 second */ os_time_delay ( OS_TICKS_PER_SEC * 2 ); } } And finally, we'll take care of that co2_read_event() function: int co2_read_event ( void ) { int value ; enum senseair_read_type type = SENSEAIR_CO2 ; uint16_t chr_val_handle ; int rc ; value = senseair_read ( type ); if ( value >= 0 ) { console_printf ( \"Got %d\\n\" , value ); } else { console_printf ( \"Error while reading: %d\\n\" , value ); goto err ; } gatt_co2_val = value ; rc = ble_gatts_find_chr ( &gatt_svr_svc_co2_uuid . u , BLE_UUID16_DECLARE ( CO2_SNS_VAL ), NULL , &chr_val_handle ); assert ( rc == 0 ); ble_gatts_chr_updated ( chr_val_handle ); return ( 0 ); err : return ( rc ); } You'll notice that it looks eeirily similar to a portion of the shell event we created earlier. This one simply reads and updates the CO 2 value and sends that over BLE to any connected clients instead. We can now build, create-image and load the app onto our Arduino Primo board, and then connect and see the updated values! The image below shows the results using MyNewt Sensor Reader, a Mac OS X app developed for connecting to MyNewt devices over Bluetooth but you can also use LightBlue or any other application that can connect to, and read, Bluetooth data. Congratulations!!","title":"Add Bluetooth GATT Services"},{"location":"os/tutorials/air_quality_sensor/","text":"Air quality sensor project Setting up source tree for stuff you need To start with, you need to create a new project under which you will do this development. So you type in: $ mkdir $HOME/src $ cd $HOME/src $ newt new air_quality Let's say you are using Arduino Primo -- which is based on the Nordic Semi NRF52 chip -- as the platform. You know you need the board support package for that hardware. You can look up its location, add it your project, and fetch that along with the core OS components. Luckily, the Arduino Primo is supported in the Mynewt Core, so there's nothing much to do here. Your project.yml file should look like this: [user@IsMyLaptop:~/src/air_quality]$ emacs project.yml & [user@IsMyLaptop:~/src/air_quality]$ cat project.yml project.name: \"air_quality\" project.repositories: - apache-mynewt-core # Use github's distribution mechanism for core ASF libraries. # This provides mirroring automatically for us. # repository.apache-mynewt-core: type: github vers: 0-latest user: apache repo: incubator-mynewt-core [user@IsMyLaptop:~/src/air_quality]$ newt install apache-mynewt-core [user@IsMyLaptop:~/src/air_quality]$ ls repos/ apache-mynewt-core Good. You want to make sure you have all the needed bits for supporting your board; so you decide to build the blinky project for the platform first. Now create a target for it and build it. Easiest way to proceed is to copy the existing target for blinky, and modify it to build for Arduino Primo board. [user@IsMyLaptop:~/src/air_quality]$ newt target copy my_blinky_sim blink_primo Target successfully copied; targets/my_blinky_sim --> targets/blink_primo [user@IsMyLaptop:~/src/air_quality]$ newt target set blink_primo bsp=@apache-mynewt-core/hw/bsp/arduino_primo_nrf52 Target targets/blink_nrf successfully set target.bsp to @apache-mynewt-core/hw/bsp/arduino_primo_nrf52 [user@IsMyLaptop:~/src/air_quality]$ newt build blink_primo Compiling hal_bsp.c ... Linking blinky.elf App successfully built: /Users/user/src/air_quality/bin/blink_primo/apps/blinky/blinky.elf Good. You know that this platform uses bootloader, which means you have to create a target for that too. [user@IsMyLaptop:~/src/air_quality]$ newt target create boot_primo Target targets/boot_nrf successfully created [user@IsMyLaptop:~/src/air_quality]$ newt target show @apache-mynewt-core/targets/unittest bsp=hw/bsp/native build_profile=debug compiler=compiler/sim targets/blink_primo app=apps/blinky bsp=@apache-mynewt-core/hw/bsp/arduino_primo_nrf52 build_profile=debug targets/boot_primo targets/my_blinky_sim app=apps/blinky bsp=@apache-mynewt-core/hw/bsp/native build_profile=debug [user@IsMyLaptop:~/src/air_quality]$ newt target set boot_nrf bsp=@apache-mynewt-core/hw/bsp/arduino_primo_nrf52 Target targets/boot_nrf successfully set target.bsp to @apache-mynewt-core/hw/bsp/arduino_primo_nrf52 [user@IsMyLaptop:~/src/air_quality]$ newt target set boot_nrf app=@apache-mynewt-core/apps/boot Target targets/boot_nrf successfully set target.app to @apache-mynewt-core/apps/boot [user@IsMyLaptop:~/src/air_quality]$ newt target set boot_nrf build_profile=optimized Target targets/boot_nrf successfully set target.build_profile to optimized And then build it, and load it onto the board. newt build boot_primo .... Linking boot.elf App successfully built: /Users/user/src/air_quality/bin/boot_primo/apps/boot/boot.elf [user@IsMyLaptop:~/src/air_quality] $ newt load boot_primo At this point, you may (or may not) see a bunch of error messages about not being able to connect to your board, not being able to load the image, etc. If that's the case, and you haven't already, you should most definitely go worth through the blinky_primo tutorial so that you can properly communicate with your board. Next you must download the targets to board, and see that the LED actually blinks. You plug in the Arduino Primo board to your laptop, and say: [user@IsMyLaptop:~/src/air_quality]$ newt load blink_primo Loading app image into slot 1 Error: couldn't open /Users/user/src/air_quality/bin/blink_primo/apps/blinky/blinky.img Error: exit status 1 load - Load app image to target for <target-name>. Usage: newt load [flags] Examples: newt load <target-name> Global Flags: -l, --loglevel string Log level, defaults to WARN. (default \"WARN\") -o, --outfile string Filename to tee log output to -q, --quiet Be quiet; only display error output. -s, --silent Be silent; don't output anything. -v, --verbose Enable verbose output when executing commands. exit status 1 Ah. Forgot to create an image out of the blinky binary. Note that every time you want to build and load a new firmware image to a target board, you need to run 'create-image' on it. [user@IsMyLaptop:~/src/air_quality]$ newt create-image blink_primo 0.0.1 App image successfully generated: /Users/user/src/air_quality/bin/blink_primo/apps/blinky/blinky.img Build manifest: /Users/user/src/air_quality/bin/blink_nrf/apps/blinky/manifest.json [user@IsMyLaptop:~/src/air_quality]$ newt load blink_primo And it's blinking. Shortcut for doing build/create-image/load/debug steps all in one is 'newt run' command. Check out the usage from command line help. Create test project Now that you have your system setup, you can start creating your own stuff. First you want to create a project for yourself - you could start by using blinky as a project template, but since we're going to want to be able to access the data via Bluetooth, let's use the bleprph Bluetooth Peripheral project instead. [user@IsMyLaptop:~/src/air_quality]$ mkdir apps/air_quality [user@IsMyLaptop:~/src/air_quality]$ cp repos/apache-mynewt-core/apps/bleprph/pkg.yml apps/air_quality/ [user@IsMyLaptop:~/src/air_quality]$ cp -Rp repos/apache-mynewt-core/apps/bleprph/src apps/air_quality/ Then you modify the apps/air_quality/pkg.yml for air_quality in order to change the pkg.name to be apps/air_quality . You'll need to add the @apache-mynewt-core/ path to all the package dependencies, since the app no longer resides within the apache-mynewt-core repository. [user@IsMyLaptop:~/src/air_quality]$ cat apps/air_quality/pkg.yml pkg.name: apps/air_quality pkg.type: app pkg.description: BLE Air Quality application. pkg.author: \"Apache Mynewt <dev@mynewt.incubator.apache.org>\" pkg.homepage: \"http://mynewt.apache.org/\" pkg.keywords: pkg.deps: - \"@apache-mynewt-core/kernel/os\" - \"@apache-mynewt-core/sys/shell\" - \"@apache-mynewt-core/sys/stats/full\" - \"@apache-mynewt-core/sys/log/full\" - \"@apache-mynewt-core/mgmt/newtmgr\" - \"@apache-mynewt-core/mgmt/newtmgr/transport/ble\" - \"@apache-mynewt-core/net/nimble/controller\" - \"@apache-mynewt-core/net/nimble/host\" - \"@apache-mynewt-core/net/nimble/host/services/ans\" - \"@apache-mynewt-core/net/nimble/host/services/gap\" - \"@apache-mynewt-core/net/nimble/host/services/gatt\" - \"@apache-mynewt-core/net/nimble/host/store/ram\" - \"@apache-mynewt-core/net/nimble/transport/ram\" - \"@apache-mynewt-core/sys/console/full\" - \"@apache-mynewt-core/sys/sysinit\" - \"@apache-mynewt-core/sys/id\" And create a target for it: [user@IsMyLaptop:~/src/air_quality]$ newt target create air_q Target targets/air_q successfully created [user@IsMyLaptop:~/src/air_quality]$ newt target set air_q bsp=@apache-mynewt-core/hw/bsp/arduino_primo_nrf52 Target targets/air_q successfully set target.bsp to @apache-mynewt-core/hw/bsp/arduino_primo_nrf52 [user@IsMyLaptop:~/src/air_quality]$ newt target set air_q app=apps/air_quality Target targets/air_q successfully set target.app to apps/air_quality [user@IsMyLaptop:~/src/air_quality]$ newt target set air_q build_profile=debug Target targets/air_q successfully set target.build_profile to debug [user@IsMyLaptop:~/src/air_quality]$ newt build air_q .... Linking /Users/dsimmons/dev/myproj/bin/targets/air_q/app/apps/air_quality/air_quality.elf Target successfully built: targets/air_q Create packages for drivers One of the sensors you want to enable is SenseAir K30, which will connect to the board over a serial port. To start development of the driver, you first need to create a package description for it, and add stubs for sources. The first thing to do is to create the directory structure for your driver: [user@IsMyLaptop:~/src/air_quality]$ mkdir -p libs/my_drivers/senseair/include/senseair [user@IsMyLaptop:~/src/air_quality]$ mkdir -p libs/my_drivers/senseair/src Now you can add the files you need. You'll need a pkg.yml to describe the driver, and then header stub followed by source stub. [user@IsMyLaptop:~/src/air_quality]$ cat libs/my_drivers/senseair/pkg.yml # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you 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. # pkg . name: libs/my_drivers/senseair pkg . description: Host side of the nimble Bluetooth Smart stack . pkg . author: \"Apache Mynewt <dev@mynewt.incubator.apache.org>\" pkg . homepage: \"http://mynewt.apache.org/\" pkg . keywords: - ble - bluetooth pkg . deps: - \"@apache-mynewt-core/kernel/os\" [user@IsMyLaptop:~/src/air_quality]$ cat libs/my_drivers/senseair/include/senseair/senseair.h /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you 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. */ #ifndef _SENSEAIR_H_ #define _SENSEAIR_H_ void senseair_init ( void ); #endif /* _SENSEAIR_H_ */ [user@IsMyLaptop:~/src/air_quality]$ cat libs/my_drivers/senseair/src/senseair.c /** * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you 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. */ void senseair_init ( void ) { } And add dependency to this package in your project yml file. Here's the listing from apps/air_quality/pkg.yml pkg.name: apps/air_quality pkg.type: app pkg.description: Air quality sensor test pkg.keywords: pkg.deps: - \"@apache-mynewt-core/libs/console/full\" - \"@apache-mynewt-core/libs/newtmgr\" - \"@apache-mynewt-core/libs/os\" - \"@apache-mynewt-core/libs/shell\" - \"@apache-mynewt-core/sys/config\" - \"@apache-mynewt-core/sys/log/full\" - \"@apache-mynewt-core/sys/stats/full\" - libs/my_drivers/senseair And add a call to your main() to initialize this driver. [user@IsMyLaptop:~/src/air_quality]$ diff project/blinky/src/main.c project/air_quality/src/main.c 28a29 > #include <senseair/senseair.h> 190a192 > senseair_init(); [user@IsMyLaptop:~/src/air_quality The ble_prph app runs everything in one task handler. For this project, we're going to add a second task handler to respond to the shell, and then handle communicating with the senseair sensor for us. /** shell task settings. */ #define SHELL_TASK_PRIO 2 #define SHELL_STACK_SIZE (OS_STACK_ALIGN(336)) struct os_eventq shell_evq ; struct os_task shell_task ; bssnz_t os_stack_t shell_stack [ SHELL_STACK_SIZE ]; That defines the task, now we need to initialize it, add a task handler, and we're going to use this task as our default task handler. /** * Event loop for the main shell task. */ static void shell_task_handler ( void *unused ) { while ( 1 ) { os_eventq_run ( &shell_evq ); } } And in your main() add: /* Initialize shell eventq */ os_eventq_init ( &shell_evq ); /* Create the shell task. * All shell operations are performed in this task. */ os_task_init ( &shell_task , \"shell\" , shell_task_handler , NULL , SHELL_TASK_PRIO , OS_WAIT_FOREVER , shell_stack , SHELL_STACK_SIZE ); Don't forget to change your default task handler! os_eventq_dflt_set ( &shell_evq ); And then build it to make sure all goes well. [user@IsMyLaptop:~/src/air_quality]$ newt build air_q Compiling senseair.c Archiving senseair.a Linking air_quality.elf App successfully built: /Users/user/src/air_quality/bin/air_q/apps/air_quality/air_quality.elf All looks good. Add CLI commands for testing drivers While developing the driver, you want to issue operations from console asking it to do stuff. We'll assume that you've already worked through the tutorial on how to enable the CLI , so all we'll need to do is add the propper values to the project's syscfg.yml file: [user@IsMyLaptop:~/src/air_quality]$ cat targets/air_q/syscfg.yml syscfg.vals: # Set as per blinky_primo OPENOCD_DEBUG: 1 # Enable the shell task. SHELL_TASK: 1 STATS_CLI: 1 CONSOLE_TICKS: 1 CONSOLE_PROMPT: 1 Then register your senseair command with the shell by adding the following to libs/my_drivers/senseair/src/senseair.c #include <shell/shell.h> #include <console/console.h> #include <assert.h> static int senseair_shell_func ( int argc , char **argv ); static struct shell_cmd senseair_cmd = { . sc_cmd = \"senseair\" , . sc_cmd_func = senseair_shell_func , }; void senseair_init ( void ) { int rc ; rc = shell_cmd_register ( &senseair_cmd ); assert ( rc == 0 ); } static int senseair_shell_func ( int argc , char **argv ) { console_printf ( \"Yay! Somebody called!\\n\" ); return 0 ; } Now you can you build this, download to target, and start minicom on your console port. If you haven't already, familiarize yourself with the tutorial on how to connect a serial port to your board here . You'll need to wire up your Board to a Serial converter first. On the Arduino Primo Board pin 1 is TX and pin 0 is RX so wire 1 to RX on your serial board, and 0 to TX on your serial board. [user@IsMyLaptop:~]$ minicom -D /dev/tty.usbserial-AH02MIE2 Welcome to minicom 2.7 OPTIONS: Compiled on Oct 12 2015, 07:48:30. Port /dev/tty.usbserial-AH02MIE2, 13:44:40 Press CTRL-X Z for help on special keys ? 419: > ? Commands: 641: stat echo ? prompt ticks tasks 643: mempools date senseair 644: > senseair Yay! Somebody called! 1125: > 53611: > tasks Tasks: 54047: task pri tid runtime csw stksz stkuse lcheck ncheck flg 54057: idle 255 0 54048 66890 64 30 0 0 0 54068: ble_ll 0 1 9 64986 80 58 0 0 0 54079: bleprph 1 2 0 1 336 32 0 0 0 54090: shell 2 3 0 2077 336 262 0 0 0 54101: > That's great. Your shell task is running, and is responding appropriately! You can connect the hardware to your board and start developing code for the driver itself. Use of HAL for drivers The sensor has a serial port connection, and that's how you are going to connect to it. Your original BSP, hw/bsp/arduino_primo_nrf52, has two UARTs set up. We're using one for our shell/console. It also has a second UART set up as a 'bit-bang' UART but since the SenseAir only needs to communicate at 9600 baud, this bit-banged uart is plenty fast enough. You'll have to make a small change to the syscfg.yml file in your project's target directory to change the pin definitions for this second UART. Those changes are as follows: UART_0_PIN_TX: 23 UART_0_PIN_RX: 24 With this in place, you can refer to serial port where your SenseAir sensor by a logical number. This makes the code more platform independent - you could connect this sensor to another board, like Olimex. You will also use the HAL UART abstraction to do the UART port setup and data transfer. That way you don't need to have any platform dependent pieces within your little driver. You will now see what the driver code ends up looking like. Here's the header file, filled in from the stub you created earlier. /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you 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. */ #ifndef _SENSEAIR_H_ #define _SENSEAIR_H_ enum senseair_read_type { SENSEAIR_CO2 , }; int senseair_init ( int uartno ); int senseair_read ( enum senseair_read_type ); #endif /* _SENSEAIR_H_ */ As you can see, logical UART number has been added to the init routine. A 'read' function has been added, which is a blocking read. If you were making a commercial product, you would probably have a callback for reporting the results. And here is the source for the driver. /** * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * \"License\"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include <string.h> #include <shell/shell.h> #include <console/console.h> #include <os/os.h> #include <hal/hal_uart.h> #include \"senseair/senseair.h\" static const uint8_t cmd_read_co2 [] = { 0xFE , 0X44 , 0X00 , 0X08 , 0X02 , 0X9F , 0X25 }; static int senseair_shell_func ( int argc , char **argv ); static struct shell_cmd senseair_cmd = { . sc_cmd = \"senseair\" , . sc_cmd_func = senseair_shell_func , }; struct senseair { int uart ; struct os_sem sema ; const uint8_t *tx_data ; int tx_off ; int tx_len ; uint8_t rx_data [ 32 ]; int rx_off ; int value ; } senseair ; static int senseair_tx_char ( void *arg ) { struct senseair *s = &senseair ; int rc ; if ( s->tx_off >= s->tx_len ) { /* * Command tx finished. */ s->tx_data = NULL ; return -1 ; } rc = s->tx_data [ s->tx_off ]; s->tx_off++ ; return rc ; } /* * CRC for modbus over serial port. */ static const uint16_t mb_crc_tbl [] = { 0x0000 , 0xcc01 , 0xd801 , 0x1400 , 0xf001 , 0x3c00 , 0x2800 , 0xe401 , 0xa001 , 0x6c00 , 0x7800 , 0xb401 , 0x5000 , 0x9c01 , 0x8801 , 0x4400 }; static uint16_t mb_crc ( const uint8_t *data , int len , uint16_t crc ) { while ( len-- > 0 ) { crc ^= *data++ ; crc = ( crc >> 4 ) ^ mb_crc_tbl [ crc & 0xf ]; crc = ( crc >> 4 ) ^ mb_crc_tbl [ crc & 0xf ]; } return crc ; } static int mb_crc_check ( const void *pkt , int len ) { uint16_t crc , cmp ; uint8_t *bp = ( uint8_t * ) pkt ; if ( len < sizeof ( crc ) + 1 ) { return -1 ; } crc = mb_crc ( pkt , len - 2 , 0xffff ); cmp = bp [ len - 2 ] | ( bp [ len - 1 ] << 8 ); if ( crc != cmp ) { return -1 ; } else { return 0 ; } } static int senseair_rx_char ( void *arg , uint8_t data ) { struct senseair *s = ( struct senseair * ) arg ; int rc ; if ( s->rx_off >= sizeof ( s->rx_data )) { s->rx_off = 0 ; } s->rx_data [ s->rx_off ] = data ; s->rx_off++ ; if ( s->rx_off == 7 ) { rc = mb_crc_check ( s->rx_data , s->rx_off ); if ( rc == 0 ) { s->value = s->rx_data [ 3 ] * 256 + s->rx_data [ 4 ]; os_sem_release ( &s->sema ); } } return 0 ; } void senseair_tx ( struct senseair *s , const uint8_t *tx_data , int data_len ) { s->tx_data = tx_data ; s->tx_len = data_len ; s->tx_off = 0 ; s->rx_off = 0 ; hal_uart_start_tx ( s->uart ); } int senseair_read ( enum senseair_read_type type ) { struct senseair *s = &senseair ; const uint8_t *cmd ; int cmd_len ; int rc ; if ( s->tx_data ) { /* * busy */ return -1 ; } switch ( type ) { case SENSEAIR_CO2 : cmd = cmd_read_co2 ; cmd_len = sizeof ( cmd_read_co2 ); break ; default : return -1 ; } senseair_tx ( s , cmd , cmd_len ); rc = os_sem_pend ( &s->sema , OS_TICKS_PER_SEC / 2 ); if ( rc == OS_TIMEOUT ) { /* * timeout */ return -2 ; } return s->value ; } static int senseair_shell_func ( int argc , char **argv ) { int value ; enum senseair_read_type type ; if ( argc < 2 ) { usage : console_printf ( \"%s co2\\n\" , argv [ 0 ]); return 0 ; } if ( !strcmp ( argv [ 1 ], \"co2\" )) { type = SENSEAIR_CO2 ; } else { goto usage ; } value = senseair_read ( type ); if ( value >= 0 ) { console_printf ( \"Got %d\\n\" , value ); } else { console_printf ( \"Error while reading: %d\\n\" , value ); } return 0 ; } int senseair_init ( int uartno ) { int rc ; struct senseair *s = &senseair ; rc = shell_cmd_register ( &senseair_cmd ); if ( rc ) { return rc ; } rc = os_sem_init ( &s->sema , 1 ); if ( rc ) { return rc ; } rc = hal_uart_init_cbs ( uartno , senseair_tx_char , NULL , senseair_rx_char , &senseair ); if ( rc ) { return rc ; } rc = hal_uart_config ( uartno , 9600 , 8 , 1 , HAL_UART_PARITY_NONE , HAL_UART_FLOW_CTL_NONE ); if ( rc ) { return rc ; } s->uart = uartno ; return 0 ; } And your modified main() for senseair driver init. int main ( int argc , char **argv ) { .... senseair_init ( 0 ); .... } You can see from the code that you are using the HAL interface to open a UART port, and using OS semaphore as a way of blocking the task when waiting for read response to come back from the sensor. Now comes the fun part: Hooking up the sensor! It's fun because a) hooking up a sensor is always fun and b) the SenseAir sensor's PCB is entirely unlabeled, so you'll have to trust us on how to hook it up. So here we go. You'll have to do a little soldering. I soldered some header pins to the SenseAir K30 board to make connecting wires easier using standard jumper wires, but you can also just solder wires straight to the board if you prefer. Here's what your SenseAir board should look like once it's wired up: Now that you have that wired up, let's get the Arduino Primo wired up. A couple of things to note: The Arduino Primo's 'console' UART is actually UART1. The secondary (bit-banged) UART is UART0, so that's where we'll have to hook up the SenseAir. Here's what your Arduino Primo should now look like with everything wired in: Everything is wired and you're ready to go! Build and load your new app: $ newt build air_q Building target targets/air_q Compiling apps/air_quality/src/main.c Archiving apps_air_quality.a Linking myproj/bin/targets/air_q/app/apps/air_quality/air_quality.elf Target successfully built: targets/air_q $ newt create-image air_q 1.0.0 App image succesfully generated: myproj/bin/targets/air_q/app/apps/air_quality/air_quality.img $ newt load air_q Loading app image into slot 1 Now, you should be able to connect to your serial port and read values: user@IsMyLaptop:~]$ minicom -D /dev/tty.usbserial-AH02MIE2 Welcome to minicom 2.7 OPTIONS: Compiled on Oct 12 2015, 07:48:30. Port /dev/tty.usbserial-AH02MIE2, 13:44:40 Press CTRL-X Z for help on special keys 1185: > ? Commands: 1382: stat echo ? prompt ticks tasks 1390: mempools date senseair 1395: > senseair senseair co2 2143: > senseair co2 Got 973 And you're getting valid readings! Congratulations! Next we'll hook this all up via Bluetooth so that you can read those values remotely.","title":"Basic Air Quality Sensor"},{"location":"os/tutorials/air_quality_sensor/#air-quality-sensor-project","text":"","title":"Air quality sensor project"},{"location":"os/tutorials/air_quality_sensor/#setting-up-source-tree-for-stuff-you-need","text":"To start with, you need to create a new project under which you will do this development. So you type in: $ mkdir $HOME/src $ cd $HOME/src $ newt new air_quality Let's say you are using Arduino Primo -- which is based on the Nordic Semi NRF52 chip -- as the platform. You know you need the board support package for that hardware. You can look up its location, add it your project, and fetch that along with the core OS components. Luckily, the Arduino Primo is supported in the Mynewt Core, so there's nothing much to do here. Your project.yml file should look like this: [user@IsMyLaptop:~/src/air_quality]$ emacs project.yml & [user@IsMyLaptop:~/src/air_quality]$ cat project.yml project.name: \"air_quality\" project.repositories: - apache-mynewt-core # Use github's distribution mechanism for core ASF libraries. # This provides mirroring automatically for us. # repository.apache-mynewt-core: type: github vers: 0-latest user: apache repo: incubator-mynewt-core [user@IsMyLaptop:~/src/air_quality]$ newt install apache-mynewt-core [user@IsMyLaptop:~/src/air_quality]$ ls repos/ apache-mynewt-core Good. You want to make sure you have all the needed bits for supporting your board; so you decide to build the blinky project for the platform first. Now create a target for it and build it. Easiest way to proceed is to copy the existing target for blinky, and modify it to build for Arduino Primo board. [user@IsMyLaptop:~/src/air_quality]$ newt target copy my_blinky_sim blink_primo Target successfully copied; targets/my_blinky_sim --> targets/blink_primo [user@IsMyLaptop:~/src/air_quality]$ newt target set blink_primo bsp=@apache-mynewt-core/hw/bsp/arduino_primo_nrf52 Target targets/blink_nrf successfully set target.bsp to @apache-mynewt-core/hw/bsp/arduino_primo_nrf52 [user@IsMyLaptop:~/src/air_quality]$ newt build blink_primo Compiling hal_bsp.c ... Linking blinky.elf App successfully built: /Users/user/src/air_quality/bin/blink_primo/apps/blinky/blinky.elf Good. You know that this platform uses bootloader, which means you have to create a target for that too. [user@IsMyLaptop:~/src/air_quality]$ newt target create boot_primo Target targets/boot_nrf successfully created [user@IsMyLaptop:~/src/air_quality]$ newt target show @apache-mynewt-core/targets/unittest bsp=hw/bsp/native build_profile=debug compiler=compiler/sim targets/blink_primo app=apps/blinky bsp=@apache-mynewt-core/hw/bsp/arduino_primo_nrf52 build_profile=debug targets/boot_primo targets/my_blinky_sim app=apps/blinky bsp=@apache-mynewt-core/hw/bsp/native build_profile=debug [user@IsMyLaptop:~/src/air_quality]$ newt target set boot_nrf bsp=@apache-mynewt-core/hw/bsp/arduino_primo_nrf52 Target targets/boot_nrf successfully set target.bsp to @apache-mynewt-core/hw/bsp/arduino_primo_nrf52 [user@IsMyLaptop:~/src/air_quality]$ newt target set boot_nrf app=@apache-mynewt-core/apps/boot Target targets/boot_nrf successfully set target.app to @apache-mynewt-core/apps/boot [user@IsMyLaptop:~/src/air_quality]$ newt target set boot_nrf build_profile=optimized Target targets/boot_nrf successfully set target.build_profile to optimized And then build it, and load it onto the board. newt build boot_primo .... Linking boot.elf App successfully built: /Users/user/src/air_quality/bin/boot_primo/apps/boot/boot.elf [user@IsMyLaptop:~/src/air_quality] $ newt load boot_primo At this point, you may (or may not) see a bunch of error messages about not being able to connect to your board, not being able to load the image, etc. If that's the case, and you haven't already, you should most definitely go worth through the blinky_primo tutorial so that you can properly communicate with your board. Next you must download the targets to board, and see that the LED actually blinks. You plug in the Arduino Primo board to your laptop, and say: [user@IsMyLaptop:~/src/air_quality]$ newt load blink_primo Loading app image into slot 1 Error: couldn't open /Users/user/src/air_quality/bin/blink_primo/apps/blinky/blinky.img Error: exit status 1 load - Load app image to target for <target-name>. Usage: newt load [flags] Examples: newt load <target-name> Global Flags: -l, --loglevel string Log level, defaults to WARN. (default \"WARN\") -o, --outfile string Filename to tee log output to -q, --quiet Be quiet; only display error output. -s, --silent Be silent; don't output anything. -v, --verbose Enable verbose output when executing commands. exit status 1 Ah. Forgot to create an image out of the blinky binary. Note that every time you want to build and load a new firmware image to a target board, you need to run 'create-image' on it. [user@IsMyLaptop:~/src/air_quality]$ newt create-image blink_primo 0.0.1 App image successfully generated: /Users/user/src/air_quality/bin/blink_primo/apps/blinky/blinky.img Build manifest: /Users/user/src/air_quality/bin/blink_nrf/apps/blinky/manifest.json [user@IsMyLaptop:~/src/air_quality]$ newt load blink_primo And it's blinking. Shortcut for doing build/create-image/load/debug steps all in one is 'newt run' command. Check out the usage from command line help.","title":"Setting up source tree for stuff you need"},{"location":"os/tutorials/air_quality_sensor/#create-test-project","text":"Now that you have your system setup, you can start creating your own stuff. First you want to create a project for yourself - you could start by using blinky as a project template, but since we're going to want to be able to access the data via Bluetooth, let's use the bleprph Bluetooth Peripheral project instead. [user@IsMyLaptop:~/src/air_quality]$ mkdir apps/air_quality [user@IsMyLaptop:~/src/air_quality]$ cp repos/apache-mynewt-core/apps/bleprph/pkg.yml apps/air_quality/ [user@IsMyLaptop:~/src/air_quality]$ cp -Rp repos/apache-mynewt-core/apps/bleprph/src apps/air_quality/ Then you modify the apps/air_quality/pkg.yml for air_quality in order to change the pkg.name to be apps/air_quality . You'll need to add the @apache-mynewt-core/ path to all the package dependencies, since the app no longer resides within the apache-mynewt-core repository. [user@IsMyLaptop:~/src/air_quality]$ cat apps/air_quality/pkg.yml pkg.name: apps/air_quality pkg.type: app pkg.description: BLE Air Quality application. pkg.author: \"Apache Mynewt <dev@mynewt.incubator.apache.org>\" pkg.homepage: \"http://mynewt.apache.org/\" pkg.keywords: pkg.deps: - \"@apache-mynewt-core/kernel/os\" - \"@apache-mynewt-core/sys/shell\" - \"@apache-mynewt-core/sys/stats/full\" - \"@apache-mynewt-core/sys/log/full\" - \"@apache-mynewt-core/mgmt/newtmgr\" - \"@apache-mynewt-core/mgmt/newtmgr/transport/ble\" - \"@apache-mynewt-core/net/nimble/controller\" - \"@apache-mynewt-core/net/nimble/host\" - \"@apache-mynewt-core/net/nimble/host/services/ans\" - \"@apache-mynewt-core/net/nimble/host/services/gap\" - \"@apache-mynewt-core/net/nimble/host/services/gatt\" - \"@apache-mynewt-core/net/nimble/host/store/ram\" - \"@apache-mynewt-core/net/nimble/transport/ram\" - \"@apache-mynewt-core/sys/console/full\" - \"@apache-mynewt-core/sys/sysinit\" - \"@apache-mynewt-core/sys/id\" And create a target for it: [user@IsMyLaptop:~/src/air_quality]$ newt target create air_q Target targets/air_q successfully created [user@IsMyLaptop:~/src/air_quality]$ newt target set air_q bsp=@apache-mynewt-core/hw/bsp/arduino_primo_nrf52 Target targets/air_q successfully set target.bsp to @apache-mynewt-core/hw/bsp/arduino_primo_nrf52 [user@IsMyLaptop:~/src/air_quality]$ newt target set air_q app=apps/air_quality Target targets/air_q successfully set target.app to apps/air_quality [user@IsMyLaptop:~/src/air_quality]$ newt target set air_q build_profile=debug Target targets/air_q successfully set target.build_profile to debug [user@IsMyLaptop:~/src/air_quality]$ newt build air_q .... Linking /Users/dsimmons/dev/myproj/bin/targets/air_q/app/apps/air_quality/air_quality.elf Target successfully built: targets/air_q","title":"Create test project"},{"location":"os/tutorials/air_quality_sensor/#create-packages-for-drivers","text":"One of the sensors you want to enable is SenseAir K30, which will connect to the board over a serial port. To start development of the driver, you first need to create a package description for it, and add stubs for sources. The first thing to do is to create the directory structure for your driver: [user@IsMyLaptop:~/src/air_quality]$ mkdir -p libs/my_drivers/senseair/include/senseair [user@IsMyLaptop:~/src/air_quality]$ mkdir -p libs/my_drivers/senseair/src Now you can add the files you need. You'll need a pkg.yml to describe the driver, and then header stub followed by source stub. [user@IsMyLaptop:~/src/air_quality]$ cat libs/my_drivers/senseair/pkg.yml # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you 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. # pkg . name: libs/my_drivers/senseair pkg . description: Host side of the nimble Bluetooth Smart stack . pkg . author: \"Apache Mynewt <dev@mynewt.incubator.apache.org>\" pkg . homepage: \"http://mynewt.apache.org/\" pkg . keywords: - ble - bluetooth pkg . deps: - \"@apache-mynewt-core/kernel/os\" [user@IsMyLaptop:~/src/air_quality]$ cat libs/my_drivers/senseair/include/senseair/senseair.h /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you 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. */ #ifndef _SENSEAIR_H_ #define _SENSEAIR_H_ void senseair_init ( void ); #endif /* _SENSEAIR_H_ */ [user@IsMyLaptop:~/src/air_quality]$ cat libs/my_drivers/senseair/src/senseair.c /** * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you 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. */ void senseair_init ( void ) { } And add dependency to this package in your project yml file. Here's the listing from apps/air_quality/pkg.yml pkg.name: apps/air_quality pkg.type: app pkg.description: Air quality sensor test pkg.keywords: pkg.deps: - \"@apache-mynewt-core/libs/console/full\" - \"@apache-mynewt-core/libs/newtmgr\" - \"@apache-mynewt-core/libs/os\" - \"@apache-mynewt-core/libs/shell\" - \"@apache-mynewt-core/sys/config\" - \"@apache-mynewt-core/sys/log/full\" - \"@apache-mynewt-core/sys/stats/full\" - libs/my_drivers/senseair And add a call to your main() to initialize this driver. [user@IsMyLaptop:~/src/air_quality]$ diff project/blinky/src/main.c project/air_quality/src/main.c 28a29 > #include <senseair/senseair.h> 190a192 > senseair_init(); [user@IsMyLaptop:~/src/air_quality The ble_prph app runs everything in one task handler. For this project, we're going to add a second task handler to respond to the shell, and then handle communicating with the senseair sensor for us. /** shell task settings. */ #define SHELL_TASK_PRIO 2 #define SHELL_STACK_SIZE (OS_STACK_ALIGN(336)) struct os_eventq shell_evq ; struct os_task shell_task ; bssnz_t os_stack_t shell_stack [ SHELL_STACK_SIZE ]; That defines the task, now we need to initialize it, add a task handler, and we're going to use this task as our default task handler. /** * Event loop for the main shell task. */ static void shell_task_handler ( void *unused ) { while ( 1 ) { os_eventq_run ( &shell_evq ); } } And in your main() add: /* Initialize shell eventq */ os_eventq_init ( &shell_evq ); /* Create the shell task. * All shell operations are performed in this task. */ os_task_init ( &shell_task , \"shell\" , shell_task_handler , NULL , SHELL_TASK_PRIO , OS_WAIT_FOREVER , shell_stack , SHELL_STACK_SIZE ); Don't forget to change your default task handler! os_eventq_dflt_set ( &shell_evq ); And then build it to make sure all goes well. [user@IsMyLaptop:~/src/air_quality]$ newt build air_q Compiling senseair.c Archiving senseair.a Linking air_quality.elf App successfully built: /Users/user/src/air_quality/bin/air_q/apps/air_quality/air_quality.elf All looks good.","title":"Create packages for drivers"},{"location":"os/tutorials/air_quality_sensor/#add-cli-commands-for-testing-drivers","text":"While developing the driver, you want to issue operations from console asking it to do stuff. We'll assume that you've already worked through the tutorial on how to enable the CLI , so all we'll need to do is add the propper values to the project's syscfg.yml file: [user@IsMyLaptop:~/src/air_quality]$ cat targets/air_q/syscfg.yml syscfg.vals: # Set as per blinky_primo OPENOCD_DEBUG: 1 # Enable the shell task. SHELL_TASK: 1 STATS_CLI: 1 CONSOLE_TICKS: 1 CONSOLE_PROMPT: 1 Then register your senseair command with the shell by adding the following to libs/my_drivers/senseair/src/senseair.c #include <shell/shell.h> #include <console/console.h> #include <assert.h> static int senseair_shell_func ( int argc , char **argv ); static struct shell_cmd senseair_cmd = { . sc_cmd = \"senseair\" , . sc_cmd_func = senseair_shell_func , }; void senseair_init ( void ) { int rc ; rc = shell_cmd_register ( &senseair_cmd ); assert ( rc == 0 ); } static int senseair_shell_func ( int argc , char **argv ) { console_printf ( \"Yay! Somebody called!\\n\" ); return 0 ; } Now you can you build this, download to target, and start minicom on your console port. If you haven't already, familiarize yourself with the tutorial on how to connect a serial port to your board here . You'll need to wire up your Board to a Serial converter first. On the Arduino Primo Board pin 1 is TX and pin 0 is RX so wire 1 to RX on your serial board, and 0 to TX on your serial board. [user@IsMyLaptop:~]$ minicom -D /dev/tty.usbserial-AH02MIE2 Welcome to minicom 2.7 OPTIONS: Compiled on Oct 12 2015, 07:48:30. Port /dev/tty.usbserial-AH02MIE2, 13:44:40 Press CTRL-X Z for help on special keys ? 419: > ? Commands: 641: stat echo ? prompt ticks tasks 643: mempools date senseair 644: > senseair Yay! Somebody called! 1125: > 53611: > tasks Tasks: 54047: task pri tid runtime csw stksz stkuse lcheck ncheck flg 54057: idle 255 0 54048 66890 64 30 0 0 0 54068: ble_ll 0 1 9 64986 80 58 0 0 0 54079: bleprph 1 2 0 1 336 32 0 0 0 54090: shell 2 3 0 2077 336 262 0 0 0 54101: > That's great. Your shell task is running, and is responding appropriately! You can connect the hardware to your board and start developing code for the driver itself.","title":"Add CLI commands for testing drivers"},{"location":"os/tutorials/air_quality_sensor/#use-of-hal-for-drivers","text":"The sensor has a serial port connection, and that's how you are going to connect to it. Your original BSP, hw/bsp/arduino_primo_nrf52, has two UARTs set up. We're using one for our shell/console. It also has a second UART set up as a 'bit-bang' UART but since the SenseAir only needs to communicate at 9600 baud, this bit-banged uart is plenty fast enough. You'll have to make a small change to the syscfg.yml file in your project's target directory to change the pin definitions for this second UART. Those changes are as follows: UART_0_PIN_TX: 23 UART_0_PIN_RX: 24 With this in place, you can refer to serial port where your SenseAir sensor by a logical number. This makes the code more platform independent - you could connect this sensor to another board, like Olimex. You will also use the HAL UART abstraction to do the UART port setup and data transfer. That way you don't need to have any platform dependent pieces within your little driver. You will now see what the driver code ends up looking like. Here's the header file, filled in from the stub you created earlier. /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you 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. */ #ifndef _SENSEAIR_H_ #define _SENSEAIR_H_ enum senseair_read_type { SENSEAIR_CO2 , }; int senseair_init ( int uartno ); int senseair_read ( enum senseair_read_type ); #endif /* _SENSEAIR_H_ */ As you can see, logical UART number has been added to the init routine. A 'read' function has been added, which is a blocking read. If you were making a commercial product, you would probably have a callback for reporting the results. And here is the source for the driver. /** * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * \"License\"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include <string.h> #include <shell/shell.h> #include <console/console.h> #include <os/os.h> #include <hal/hal_uart.h> #include \"senseair/senseair.h\" static const uint8_t cmd_read_co2 [] = { 0xFE , 0X44 , 0X00 , 0X08 , 0X02 , 0X9F , 0X25 }; static int senseair_shell_func ( int argc , char **argv ); static struct shell_cmd senseair_cmd = { . sc_cmd = \"senseair\" , . sc_cmd_func = senseair_shell_func , }; struct senseair { int uart ; struct os_sem sema ; const uint8_t *tx_data ; int tx_off ; int tx_len ; uint8_t rx_data [ 32 ]; int rx_off ; int value ; } senseair ; static int senseair_tx_char ( void *arg ) { struct senseair *s = &senseair ; int rc ; if ( s->tx_off >= s->tx_len ) { /* * Command tx finished. */ s->tx_data = NULL ; return -1 ; } rc = s->tx_data [ s->tx_off ]; s->tx_off++ ; return rc ; } /* * CRC for modbus over serial port. */ static const uint16_t mb_crc_tbl [] = { 0x0000 , 0xcc01 , 0xd801 , 0x1400 , 0xf001 , 0x3c00 , 0x2800 , 0xe401 , 0xa001 , 0x6c00 , 0x7800 , 0xb401 , 0x5000 , 0x9c01 , 0x8801 , 0x4400 }; static uint16_t mb_crc ( const uint8_t *data , int len , uint16_t crc ) { while ( len-- > 0 ) { crc ^= *data++ ; crc = ( crc >> 4 ) ^ mb_crc_tbl [ crc & 0xf ]; crc = ( crc >> 4 ) ^ mb_crc_tbl [ crc & 0xf ]; } return crc ; } static int mb_crc_check ( const void *pkt , int len ) { uint16_t crc , cmp ; uint8_t *bp = ( uint8_t * ) pkt ; if ( len < sizeof ( crc ) + 1 ) { return -1 ; } crc = mb_crc ( pkt , len - 2 , 0xffff ); cmp = bp [ len - 2 ] | ( bp [ len - 1 ] << 8 ); if ( crc != cmp ) { return -1 ; } else { return 0 ; } } static int senseair_rx_char ( void *arg , uint8_t data ) { struct senseair *s = ( struct senseair * ) arg ; int rc ; if ( s->rx_off >= sizeof ( s->rx_data )) { s->rx_off = 0 ; } s->rx_data [ s->rx_off ] = data ; s->rx_off++ ; if ( s->rx_off == 7 ) { rc = mb_crc_check ( s->rx_data , s->rx_off ); if ( rc == 0 ) { s->value = s->rx_data [ 3 ] * 256 + s->rx_data [ 4 ]; os_sem_release ( &s->sema ); } } return 0 ; } void senseair_tx ( struct senseair *s , const uint8_t *tx_data , int data_len ) { s->tx_data = tx_data ; s->tx_len = data_len ; s->tx_off = 0 ; s->rx_off = 0 ; hal_uart_start_tx ( s->uart ); } int senseair_read ( enum senseair_read_type type ) { struct senseair *s = &senseair ; const uint8_t *cmd ; int cmd_len ; int rc ; if ( s->tx_data ) { /* * busy */ return -1 ; } switch ( type ) { case SENSEAIR_CO2 : cmd = cmd_read_co2 ; cmd_len = sizeof ( cmd_read_co2 ); break ; default : return -1 ; } senseair_tx ( s , cmd , cmd_len ); rc = os_sem_pend ( &s->sema , OS_TICKS_PER_SEC / 2 ); if ( rc == OS_TIMEOUT ) { /* * timeout */ return -2 ; } return s->value ; } static int senseair_shell_func ( int argc , char **argv ) { int value ; enum senseair_read_type type ; if ( argc < 2 ) { usage : console_printf ( \"%s co2\\n\" , argv [ 0 ]); return 0 ; } if ( !strcmp ( argv [ 1 ], \"co2\" )) { type = SENSEAIR_CO2 ; } else { goto usage ; } value = senseair_read ( type ); if ( value >= 0 ) { console_printf ( \"Got %d\\n\" , value ); } else { console_printf ( \"Error while reading: %d\\n\" , value ); } return 0 ; } int senseair_init ( int uartno ) { int rc ; struct senseair *s = &senseair ; rc = shell_cmd_register ( &senseair_cmd ); if ( rc ) { return rc ; } rc = os_sem_init ( &s->sema , 1 ); if ( rc ) { return rc ; } rc = hal_uart_init_cbs ( uartno , senseair_tx_char , NULL , senseair_rx_char , &senseair ); if ( rc ) { return rc ; } rc = hal_uart_config ( uartno , 9600 , 8 , 1 , HAL_UART_PARITY_NONE , HAL_UART_FLOW_CTL_NONE ); if ( rc ) { return rc ; } s->uart = uartno ; return 0 ; } And your modified main() for senseair driver init. int main ( int argc , char **argv ) { .... senseair_init ( 0 ); .... } You can see from the code that you are using the HAL interface to open a UART port, and using OS semaphore as a way of blocking the task when waiting for read response to come back from the sensor. Now comes the fun part: Hooking up the sensor! It's fun because a) hooking up a sensor is always fun and b) the SenseAir sensor's PCB is entirely unlabeled, so you'll have to trust us on how to hook it up. So here we go. You'll have to do a little soldering. I soldered some header pins to the SenseAir K30 board to make connecting wires easier using standard jumper wires, but you can also just solder wires straight to the board if you prefer. Here's what your SenseAir board should look like once it's wired up: Now that you have that wired up, let's get the Arduino Primo wired up. A couple of things to note: The Arduino Primo's 'console' UART is actually UART1. The secondary (bit-banged) UART is UART0, so that's where we'll have to hook up the SenseAir. Here's what your Arduino Primo should now look like with everything wired in: Everything is wired and you're ready to go! Build and load your new app: $ newt build air_q Building target targets/air_q Compiling apps/air_quality/src/main.c Archiving apps_air_quality.a Linking myproj/bin/targets/air_q/app/apps/air_quality/air_quality.elf Target successfully built: targets/air_q $ newt create-image air_q 1.0.0 App image succesfully generated: myproj/bin/targets/air_q/app/apps/air_quality/air_quality.img $ newt load air_q Loading app image into slot 1 Now, you should be able to connect to your serial port and read values: user@IsMyLaptop:~]$ minicom -D /dev/tty.usbserial-AH02MIE2 Welcome to minicom 2.7 OPTIONS: Compiled on Oct 12 2015, 07:48:30. Port /dev/tty.usbserial-AH02MIE2, 13:44:40 Press CTRL-X Z for help on special keys 1185: > ? Commands: 1382: stat echo ? prompt ticks tasks 1390: mempools date senseair 1395: > senseair senseair co2 2143: > senseair co2 Got 973 And you're getting valid readings! Congratulations! Next we'll hook this all up via Bluetooth so that you can read those values remotely.","title":"Use of HAL for drivers"},{"location":"os/tutorials/arduino_zero/","text":"Blinky, your \"Hello World!\", on Arduino Zero This tutorial shows you how to create, build and run the Blinky application on an Arduino Zero board. Prerequisites Meet the prerequisites listed in Project Blinky . Have an Arduino Zero board. Note: There are many flavors of Arduino. Make sure you are using an Arduino Zero. See below for the versions of Arduino Zero that are compatible with this tutorial. Install the OpenOCD debugger . This tutorial uses the Arduino Zero Pro board. The tutorial has been tested on the following three Arduino Zero boards - Zero, M0 Pro, and Zero-Pro. Mynewt has not been tested on Arduino M0 which has no internal debugger support. Create a Project Create a new project if you do not have an existing one. You can skip this step and proceed to fetch external packages if you already created a project. Run the following commands to create a new project: $ mkdir ~/dev $ cd ~/dev $ newt new myproj Downloading project skeleton from apache/incubator-mynewt-blinky... Installing skeleton in myproj... Project myproj successfully created. $ cd myproj $ newt install apache-mynewt-core $ Fetch External Packages Mynewt uses source code provided directly from the chip manufacturer for low level operations. Sometimes this code is licensed only for the specific manufacturer of the chipset and cannot live in the Apache Mynewt repository. That happens to be the case for the Arduino Zero board which uses Atmel SAMD21. Runtime's github repository hosts such external third-party packages and the newt tool can fetch them. To fetch the package with MCU support for Atmel SAMD21 for Arduino Zero from the Runtime git repository, you need to add the repository to the project.yml file in your base project directory. Here is an example project.yml file with the Arduino Zero repository added. The sections with mynewt_arduino_zero that need to be added to your project file are highlighted. Note: On Windows platforms: You need to set vers to 0-dev and use the latest master branch for both repositories. $ more project.yml project.name: \"my_project\" project.repositories: - apache-mynewt-core - mynewt_arduino_zero repository.apache-mynewt-core: type: github vers: 1-latest user: apache repo: incubator-mynewt-core repository.mynewt_arduino_zero: type: github vers: 1-latest user: runtimeco repo: mynewt_arduino_zero $ Install the project dependencies using the newt install command (you can specify -v for verbose output): $ newt install apache-mynewt-core mynewt_arduino_zero $ NOTE: If there has been a new release of a repo used in your project since you last installed it, the 1-latest version for the repo in the project.yml file will refer to the new release and will not match the installed files. In that case you will get an error message saying so and you will need to run newt upgrade to overwrite the existing files with the latest codebase. You need to create two targets for the Arduino Zero Pro board, one for the bootloader and one for the Blinky application. Run the following newt target commands, from your project directory, to create a bootloader target. We name the target arduino_boot . $ newt target create arduino_boot $ newt target set arduino_boot bsp=@mynewt_arduino_zero/hw/bsp/arduino_zero Target targets/arduino_boot successfully created $ newt target set arduino_boot app=@apache-mynewt-core/apps/boot Target targets/arduino_boot successfully set target.app to @apache-mynewt-core/apps/boot $ newt target set arduino_boot build_profile=optimized Target targets/arduino_boot successfully set target.build_profile to optimized $ newt target set arduino_boot syscfg=BSP_ARDUINO_ZERO_PRO=1 Target targets/arduino_boot successfully set target.syscfg to BSP_ARDUINO_ZERO_PRO=1 $ Note: If you have an Arduino Zero instead of an Arduino Zero Pro or Arduino M0 Pro board, replace BSP_ARDUINO_ZERO_PRO with BSP_ARDUINO_ZERO in the last newt target set command. These commands perform the following: Create a target named arduino_boot for the Arduino Zero Bootloader. Set the application for the arduino_boot target to the default Apache Mynewt bootloader ( @apache-mynewt-core/apps/boot ) Set the board support package for the target to @mynewt_arduino_zero/hw/bsp/arduino_zero . This is a reference to the downloaded Arduino Zero support from Github. Use the \"optimized\" build profile for the arduino_boot target. This instructs Newt to generate smaller and more efficient code for this target. This setting is necessary due to the bootloader's strict size constraints. Sets the system configuration setting for Board Support Package to support the Arduino Zero Pro. See the Concepts section for more information on setting options. Create a Target for the Blinky Application Run the following newt target commands to create the Blinky application target. We name the application target arduino_blinky . $ newt target create arduino_blinky Target targets/arduino_blinky successfully created $ newt target set arduino_blinky app=apps/blinky Target targets/arduino_blinky successfully set target.app to apps/blinky $ newt target set arduino_blinky bsp=@mynewt_arduino_zero/hw/bsp/arduino_zero Target targets/arduino_blinky successfully set target.bsp to @mynewt_arduino_zero/hw/bsp/arduino_zero $ newt target set arduino_blinky build_profile=debug Target targets/arduino_blinky successfully set target.build_profile to debug $ newt target set arduino_blinky syscfg=BSP_ARDUINO_ZERO_PRO=1 Target targets/arduino_boot successfully set target.syscfg to BSP_ARDUINO_ZERO_PRO=1 $ Note: If you have an Arduino Zero instead of a Arduino Zero Pro board, replace BSP_ARDUINO_ZERO_PRO with BSP_ARDUINO_ZERO in the last newt target set command. Build the Bootloader Run the newt build arduino_boot command to build the bootloader: $ newt build arduino_boot Building target targets/arduino_boot Compiling bin/targets/arduino_boot/generated/src/arduino_boot-sysinit-app.c Compiling repos/apache-mynewt-core/boot/bootutil/src/image_rsa.c Compiling repos/apache-mynewt-core/boot/bootutil/src/image_ec.c Compiling repos/apache-mynewt-core/boot/bootutil/src/image_ec256.c Compiling bin/targets/arduino_boot/generated/src/arduino_boot-sysflash.c Compiling repos/apache-mynewt-core/boot/bootutil/src/image_validate.c Compiling repos/apache-mynewt-core/boot/bootutil/src/bootutil_misc.c Compiling repos/apache-mynewt-core/apps/boot/src/boot.c Compiling repos/apache-mynewt-core/crypto/mbedtls/src/arc4.c Compiling repos/apache-mynewt-core/boot/bootutil/src/loader.c Compiling repos/apache-mynewt-core/crypto/mbedtls/src/aes.c .... Archiving sys_mfg.a Archiving sys_sysinit.a Archiving util_mem.a Linking ~/dev/myproj/bin/targets/arduino_boot/app/apps/boot/boot.elf Target successfully built: targets/arduino_boot Build the Blinky Application Run the newt build arduino_blinky command to build the Blinky application image: $ newt build arduino_blinky Building target targets/arduino_blinky Compiling repos/apache-mynewt-core/hw/hal/src/hal_flash.c Compiling apps/blinky/src/main.c Compiling repos/mynewt_arduino_zero/hw/mcu/atmel/samd21xx/src/sam0/drivers/i2s/i2s.c Compiling repos/mynewt_arduino_zero/hw/bsp/arduino_zero/src/hal_bsp.c Compiling repos/mynewt_arduino_zero/hw/mcu/atmel/samd21xx/src/sam0/drivers/i2s/i2s_callback.c Compiling repos/mynewt_arduino_zero/hw/mcu/atmel/samd21xx/src/sam0/drivers/nvm/nvm.c ... Archiving sys_mfg.a Archiving sys_sysinit.a Archiving util_mem.a Linking ~/dev/myproj/bin/targets/arduino_blinky/app/apps/blinky/blinky.elf Target successfully built: targets/arduino_blinky Connect to the Board Connect your computer to the Arduino Zero (from now on we'll call this the target) with a Micro-USB cable through the Programming Port as shown below. Mynewt will load the image onto the board and debug the target through this port. You should see a green LED come on that indicates the board has power. No external debugger is required. The Arduino Zero comes with an internal debugger that can be accessed by Mynewt. The images below show the Arduino Zero Programming Port. Load the Bootloader onto the Board Run the newt load arduino_boot command to load the bootloader onto the board: $ newt load arduino_boot Loading bootloader $ The bootloader is loaded onto your board succesfully when the newt load command returns to the command prompt after the Loading bootloader status message. You can proceed to load and run your Blinky application image (See Run the Blinky Application ). If the newt load command outputs the following error messages, you will need to erase the board. $ newt load arduino_boot -v Loading bootloader Error: Downloading ~/dev/myproj/bin/targets/arduino_boot/app/apps/boot/boot.elf.bin to 0x0 Open On-Chip Debugger 0.9.0 (2015-11-15-05:39) Licensed under GNU GPL v2 For bug reports, read http://openocd.org/doc/doxygen/bugs.html Info : only one transport option; autoselect 'swd' adapter speed: 500 kHz adapter_nsrst_delay: 100 cortex_m reset_config sysresetreq Info : CMSIS-DAP: SWD Supported Info : CMSIS-DAP: JTAG Supported Info : CMSIS-DAP: Interface Initialised (SWD) Info : CMSIS-DAP: FW Version = 01.1F.0118 Info : SWCLK/TCK = 1 SWDIO/TMS = 1 TDI = 1 TDO = 1 nTRST = 0 nRESET = 1 Info : CMSIS-DAP: Interface ready Info : clock speed 500 kHz Info : SWD IDCODE 0x0bc11477 Info : at91samd21g18.cpu: hardware has 4 breakpoints, 2 watchpoints Error: Target not halted To erase your board, start a debug session and enter the highlighted commands at the (gdb) prompts: Note: On Windows, openocd and gdb are started in separate Windows Command Prompt terminals, and the terminals are automatically closed when you quit gdb. In addition, the output of openocd is logged to the openocd.log file in your project's base directory instead of the terminal. $ newt debug arduino_blinky (gdb) mon at91samd chip-erase chip erased chip erased (gdb) x/32wx 0 0x0: 0xffffffff 0xffffffff 0xffffffff 0xffffffff 0x10: 0xffffffff 0xffffffff 0xffffffff 0xffffffff 0x20: 0xffffffff 0xffffffff 0xffffffff 0xffffffff 0x30: 0xffffffff 0xffffffff 0xffffffff 0xffffffff 0x40: 0xffffffff 0xffffffff 0xffffffff 0xffffffff 0x50: 0xffffffff 0xffffffff 0xffffffff 0xffffffff 0x60: 0xffffffff 0xffffffff 0xffffffff 0xffffffff 0x70: 0xffffffff 0xffffffff 0xffffffff 0xffffffff (gdb) q Run the newt load arduino_boot command again after erasing the board. Reminder if you are using Docker: When working with actual hardware, remember that each board has an ID. If you swap boards and do not refresh the USB Device Filter on the VirtualBox UI, the ID might be stale and the Docker instance may not be able to see the board correctly. For example, you may see an error message like Error: unable to find CMSIS-DAP device when you try to load or run an image on the board. In that case, you need to click on the USB link in VirtualBox UI, remove the existing USB Device Filter (e.g. \"Atmel Corp. EDBG CMSIS-DAP[0101]\") by clicking on the \"Removes selected USB filter\" button, and add a new filter by clicking on the \"Adds new USB filter\" button. Run the Blinky Application After you load the bootloader successfully onto your board, you can load and run the Blinky application. Run the newt run arduino_blinky 1.0.0 command to build the arduino_blinky target (if necessary), create an image with version 1.0.0, load the image onto the board, and start a debugger session. Note The output of the debug session below is for Mac OS and Linux platforms. On Windows, openocd and gdb are started in separate Windows Command Prompt terminals. The output of openocd is logged to the openocd.log file in your project's base directory and not to the terminal. The openocd and gdb terminals will close automatically when you quit gdb. $ newt run arduino_blinky 1.0.0 App image succesfully generated: ~/dev/myproj/bin/targets/arduino_blinky/app/apps/blinky/blinky.img Loading app image into slot 1 [~/dev/myproj/repos/mynewt_arduino_zero/hw/bsp/arduino_zero/arduino_zero_debug.sh ~/dev/myproj/repos/mynewt_arduino_zero/hw/bsp/arduino_zero ~/dev/myproj/bin/targets/arduino_blinky/app/apps/blinky/blinky] Open On-Chip Debugger 0.9.0 (2015-11-15-13:10) Licensed under GNU GPL v2 For bug reports, read http://openocd.org/doc/doxygen/bugs.html Info : only one transport option; autoselect 'swd' adapter speed: 500 kHz adapter_nsrst_delay: 100 cortex_m reset_config sysresetreq Info : CMSIS-DAP: SWD Supported Info : CMSIS-DAP: JTAG Supported Info : CMSIS-DAP: Interface Initialised (SWD) Info : CMSIS-DAP: FW Version = 01.1F.0118 Info : SWCLK/TCK = 1 SWDIO/TMS = 1 TDI = 1 TDO = 1 nTRST = 0 nRESET = 1 Info : CMSIS-DAP: Interface ready Info : clock speed 500 kHz Info : SWD IDCODE 0x0bc11477 Info : at91samd21g18.cpu: hardware has 4 breakpoints, 2 watchpoints target state: halted target halted due to debug-request, current mode: Thread xPSR: 0x21000000 pc: 0x0000fca6 psp: 0x20002408 GNU gdb (GNU Tools for ARM Embedded Processors) 7.8.0.20150604-cvs Copyright (C) 2014 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html> This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. Type \"show copying\" and \"show warranty\" for details. This GDB was configured as \"--host=x86_64-apple-darwin10 --target=arm-none-eabi\". Type \"show configuration\" for configuration details. For bug reporting instructions, please see: <http://www.gnu.org/software/gdb/bugs/>. Find the GDB manual and other documentation resources online at: <http://www.gnu.org/software/gdb/documentation/>. For help, type \"help\". Type \"apropos word\" to search for commands related to \"word\"... Reading symbols from ~/dev/myproj/bin/targets/arduino_blinky/app/apps/blinky/blinky.elf...(no debugging symbols found)...done. Info : accepting 'gdb' connection on tcp/3333 Info : SAMD MCU: SAMD21G18A (256KB Flash, 32KB RAM) 0x0000fca6 in os_tick_idle () target state: halted target halted due to debug-request, current mode: Thread xPSR: 0x21000000 pc: 0x000000b8 msp: 0x20008000 target state: halted target halted due to debug-request, current mode: Thread xPSR: 0x21000000 pc: 0x000000b8 msp: 0x20008000 (gdb) r The \"remote\" target does not support \"run\". Try \"help target\" or \"continue\". (gdb) c Continuing. NOTE: The 1.0.0 is the version number to assign to the image. You may assign an arbitrary version number. If you are not providing remote upgrade, and are just developing locally, you can provide 1.0.0 for every image version. If you want the image to run without the debugger connected, simply quit the debugger and restart the board. The image you programmed will come up and run on the Arduino on the next boot! You should see the LED blink!","title":"Blinky on Arduino Zero"},{"location":"os/tutorials/arduino_zero/#blinky-your-hello-world-on-arduino-zero","text":"This tutorial shows you how to create, build and run the Blinky application on an Arduino Zero board.","title":"Blinky, your \"Hello World!\", on Arduino Zero"},{"location":"os/tutorials/arduino_zero/#prerequisites","text":"Meet the prerequisites listed in Project Blinky . Have an Arduino Zero board. Note: There are many flavors of Arduino. Make sure you are using an Arduino Zero. See below for the versions of Arduino Zero that are compatible with this tutorial. Install the OpenOCD debugger . This tutorial uses the Arduino Zero Pro board. The tutorial has been tested on the following three Arduino Zero boards - Zero, M0 Pro, and Zero-Pro. Mynewt has not been tested on Arduino M0 which has no internal debugger support.","title":"Prerequisites"},{"location":"os/tutorials/arduino_zero/#create-a-project","text":"Create a new project if you do not have an existing one. You can skip this step and proceed to fetch external packages if you already created a project. Run the following commands to create a new project: $ mkdir ~/dev $ cd ~/dev $ newt new myproj Downloading project skeleton from apache/incubator-mynewt-blinky... Installing skeleton in myproj... Project myproj successfully created. $ cd myproj $ newt install apache-mynewt-core $","title":"Create a Project"},{"location":"os/tutorials/arduino_zero/#fetch-external-packages","text":"Mynewt uses source code provided directly from the chip manufacturer for low level operations. Sometimes this code is licensed only for the specific manufacturer of the chipset and cannot live in the Apache Mynewt repository. That happens to be the case for the Arduino Zero board which uses Atmel SAMD21. Runtime's github repository hosts such external third-party packages and the newt tool can fetch them. To fetch the package with MCU support for Atmel SAMD21 for Arduino Zero from the Runtime git repository, you need to add the repository to the project.yml file in your base project directory. Here is an example project.yml file with the Arduino Zero repository added. The sections with mynewt_arduino_zero that need to be added to your project file are highlighted. Note: On Windows platforms: You need to set vers to 0-dev and use the latest master branch for both repositories. $ more project.yml project.name: \"my_project\" project.repositories: - apache-mynewt-core - mynewt_arduino_zero repository.apache-mynewt-core: type: github vers: 1-latest user: apache repo: incubator-mynewt-core repository.mynewt_arduino_zero: type: github vers: 1-latest user: runtimeco repo: mynewt_arduino_zero $ Install the project dependencies using the newt install command (you can specify -v for verbose output): $ newt install apache-mynewt-core mynewt_arduino_zero $ NOTE: If there has been a new release of a repo used in your project since you last installed it, the 1-latest version for the repo in the project.yml file will refer to the new release and will not match the installed files. In that case you will get an error message saying so and you will need to run newt upgrade to overwrite the existing files with the latest codebase. You need to create two targets for the Arduino Zero Pro board, one for the bootloader and one for the Blinky application. Run the following newt target commands, from your project directory, to create a bootloader target. We name the target arduino_boot . $ newt target create arduino_boot $ newt target set arduino_boot bsp=@mynewt_arduino_zero/hw/bsp/arduino_zero Target targets/arduino_boot successfully created $ newt target set arduino_boot app=@apache-mynewt-core/apps/boot Target targets/arduino_boot successfully set target.app to @apache-mynewt-core/apps/boot $ newt target set arduino_boot build_profile=optimized Target targets/arduino_boot successfully set target.build_profile to optimized $ newt target set arduino_boot syscfg=BSP_ARDUINO_ZERO_PRO=1 Target targets/arduino_boot successfully set target.syscfg to BSP_ARDUINO_ZERO_PRO=1 $ Note: If you have an Arduino Zero instead of an Arduino Zero Pro or Arduino M0 Pro board, replace BSP_ARDUINO_ZERO_PRO with BSP_ARDUINO_ZERO in the last newt target set command. These commands perform the following: Create a target named arduino_boot for the Arduino Zero Bootloader. Set the application for the arduino_boot target to the default Apache Mynewt bootloader ( @apache-mynewt-core/apps/boot ) Set the board support package for the target to @mynewt_arduino_zero/hw/bsp/arduino_zero . This is a reference to the downloaded Arduino Zero support from Github. Use the \"optimized\" build profile for the arduino_boot target. This instructs Newt to generate smaller and more efficient code for this target. This setting is necessary due to the bootloader's strict size constraints. Sets the system configuration setting for Board Support Package to support the Arduino Zero Pro. See the Concepts section for more information on setting options.","title":" Fetch External Packages"},{"location":"os/tutorials/arduino_zero/#create-a-target-for-the-blinky-application","text":"Run the following newt target commands to create the Blinky application target. We name the application target arduino_blinky . $ newt target create arduino_blinky Target targets/arduino_blinky successfully created $ newt target set arduino_blinky app=apps/blinky Target targets/arduino_blinky successfully set target.app to apps/blinky $ newt target set arduino_blinky bsp=@mynewt_arduino_zero/hw/bsp/arduino_zero Target targets/arduino_blinky successfully set target.bsp to @mynewt_arduino_zero/hw/bsp/arduino_zero $ newt target set arduino_blinky build_profile=debug Target targets/arduino_blinky successfully set target.build_profile to debug $ newt target set arduino_blinky syscfg=BSP_ARDUINO_ZERO_PRO=1 Target targets/arduino_boot successfully set target.syscfg to BSP_ARDUINO_ZERO_PRO=1 $ Note: If you have an Arduino Zero instead of a Arduino Zero Pro board, replace BSP_ARDUINO_ZERO_PRO with BSP_ARDUINO_ZERO in the last newt target set command.","title":"Create a Target for the Blinky Application"},{"location":"os/tutorials/arduino_zero/#build-the-bootloader","text":"Run the newt build arduino_boot command to build the bootloader: $ newt build arduino_boot Building target targets/arduino_boot Compiling bin/targets/arduino_boot/generated/src/arduino_boot-sysinit-app.c Compiling repos/apache-mynewt-core/boot/bootutil/src/image_rsa.c Compiling repos/apache-mynewt-core/boot/bootutil/src/image_ec.c Compiling repos/apache-mynewt-core/boot/bootutil/src/image_ec256.c Compiling bin/targets/arduino_boot/generated/src/arduino_boot-sysflash.c Compiling repos/apache-mynewt-core/boot/bootutil/src/image_validate.c Compiling repos/apache-mynewt-core/boot/bootutil/src/bootutil_misc.c Compiling repos/apache-mynewt-core/apps/boot/src/boot.c Compiling repos/apache-mynewt-core/crypto/mbedtls/src/arc4.c Compiling repos/apache-mynewt-core/boot/bootutil/src/loader.c Compiling repos/apache-mynewt-core/crypto/mbedtls/src/aes.c .... Archiving sys_mfg.a Archiving sys_sysinit.a Archiving util_mem.a Linking ~/dev/myproj/bin/targets/arduino_boot/app/apps/boot/boot.elf Target successfully built: targets/arduino_boot","title":"Build the Bootloader"},{"location":"os/tutorials/arduino_zero/#build-the-blinky-application","text":"Run the newt build arduino_blinky command to build the Blinky application image: $ newt build arduino_blinky Building target targets/arduino_blinky Compiling repos/apache-mynewt-core/hw/hal/src/hal_flash.c Compiling apps/blinky/src/main.c Compiling repos/mynewt_arduino_zero/hw/mcu/atmel/samd21xx/src/sam0/drivers/i2s/i2s.c Compiling repos/mynewt_arduino_zero/hw/bsp/arduino_zero/src/hal_bsp.c Compiling repos/mynewt_arduino_zero/hw/mcu/atmel/samd21xx/src/sam0/drivers/i2s/i2s_callback.c Compiling repos/mynewt_arduino_zero/hw/mcu/atmel/samd21xx/src/sam0/drivers/nvm/nvm.c ... Archiving sys_mfg.a Archiving sys_sysinit.a Archiving util_mem.a Linking ~/dev/myproj/bin/targets/arduino_blinky/app/apps/blinky/blinky.elf Target successfully built: targets/arduino_blinky","title":"Build the Blinky Application"},{"location":"os/tutorials/arduino_zero/#connect-to-the-board","text":"Connect your computer to the Arduino Zero (from now on we'll call this the target) with a Micro-USB cable through the Programming Port as shown below. Mynewt will load the image onto the board and debug the target through this port. You should see a green LED come on that indicates the board has power. No external debugger is required. The Arduino Zero comes with an internal debugger that can be accessed by Mynewt. The images below show the Arduino Zero Programming Port.","title":"Connect to the Board"},{"location":"os/tutorials/arduino_zero/#load-the-bootloader-onto-the-board","text":"Run the newt load arduino_boot command to load the bootloader onto the board: $ newt load arduino_boot Loading bootloader $ The bootloader is loaded onto your board succesfully when the newt load command returns to the command prompt after the Loading bootloader status message. You can proceed to load and run your Blinky application image (See Run the Blinky Application ). If the newt load command outputs the following error messages, you will need to erase the board. $ newt load arduino_boot -v Loading bootloader Error: Downloading ~/dev/myproj/bin/targets/arduino_boot/app/apps/boot/boot.elf.bin to 0x0 Open On-Chip Debugger 0.9.0 (2015-11-15-05:39) Licensed under GNU GPL v2 For bug reports, read http://openocd.org/doc/doxygen/bugs.html Info : only one transport option; autoselect 'swd' adapter speed: 500 kHz adapter_nsrst_delay: 100 cortex_m reset_config sysresetreq Info : CMSIS-DAP: SWD Supported Info : CMSIS-DAP: JTAG Supported Info : CMSIS-DAP: Interface Initialised (SWD) Info : CMSIS-DAP: FW Version = 01.1F.0118 Info : SWCLK/TCK = 1 SWDIO/TMS = 1 TDI = 1 TDO = 1 nTRST = 0 nRESET = 1 Info : CMSIS-DAP: Interface ready Info : clock speed 500 kHz Info : SWD IDCODE 0x0bc11477 Info : at91samd21g18.cpu: hardware has 4 breakpoints, 2 watchpoints Error: Target not halted To erase your board, start a debug session and enter the highlighted commands at the (gdb) prompts: Note: On Windows, openocd and gdb are started in separate Windows Command Prompt terminals, and the terminals are automatically closed when you quit gdb. In addition, the output of openocd is logged to the openocd.log file in your project's base directory instead of the terminal. $ newt debug arduino_blinky (gdb) mon at91samd chip-erase chip erased chip erased (gdb) x/32wx 0 0x0: 0xffffffff 0xffffffff 0xffffffff 0xffffffff 0x10: 0xffffffff 0xffffffff 0xffffffff 0xffffffff 0x20: 0xffffffff 0xffffffff 0xffffffff 0xffffffff 0x30: 0xffffffff 0xffffffff 0xffffffff 0xffffffff 0x40: 0xffffffff 0xffffffff 0xffffffff 0xffffffff 0x50: 0xffffffff 0xffffffff 0xffffffff 0xffffffff 0x60: 0xffffffff 0xffffffff 0xffffffff 0xffffffff 0x70: 0xffffffff 0xffffffff 0xffffffff 0xffffffff (gdb) q Run the newt load arduino_boot command again after erasing the board. Reminder if you are using Docker: When working with actual hardware, remember that each board has an ID. If you swap boards and do not refresh the USB Device Filter on the VirtualBox UI, the ID might be stale and the Docker instance may not be able to see the board correctly. For example, you may see an error message like Error: unable to find CMSIS-DAP device when you try to load or run an image on the board. In that case, you need to click on the USB link in VirtualBox UI, remove the existing USB Device Filter (e.g. \"Atmel Corp. EDBG CMSIS-DAP[0101]\") by clicking on the \"Removes selected USB filter\" button, and add a new filter by clicking on the \"Adds new USB filter\" button.","title":"Load the Bootloader onto the Board"},{"location":"os/tutorials/arduino_zero/#run-the-blinky-application","text":"After you load the bootloader successfully onto your board, you can load and run the Blinky application. Run the newt run arduino_blinky 1.0.0 command to build the arduino_blinky target (if necessary), create an image with version 1.0.0, load the image onto the board, and start a debugger session. Note The output of the debug session below is for Mac OS and Linux platforms. On Windows, openocd and gdb are started in separate Windows Command Prompt terminals. The output of openocd is logged to the openocd.log file in your project's base directory and not to the terminal. The openocd and gdb terminals will close automatically when you quit gdb. $ newt run arduino_blinky 1.0.0 App image succesfully generated: ~/dev/myproj/bin/targets/arduino_blinky/app/apps/blinky/blinky.img Loading app image into slot 1 [~/dev/myproj/repos/mynewt_arduino_zero/hw/bsp/arduino_zero/arduino_zero_debug.sh ~/dev/myproj/repos/mynewt_arduino_zero/hw/bsp/arduino_zero ~/dev/myproj/bin/targets/arduino_blinky/app/apps/blinky/blinky] Open On-Chip Debugger 0.9.0 (2015-11-15-13:10) Licensed under GNU GPL v2 For bug reports, read http://openocd.org/doc/doxygen/bugs.html Info : only one transport option; autoselect 'swd' adapter speed: 500 kHz adapter_nsrst_delay: 100 cortex_m reset_config sysresetreq Info : CMSIS-DAP: SWD Supported Info : CMSIS-DAP: JTAG Supported Info : CMSIS-DAP: Interface Initialised (SWD) Info : CMSIS-DAP: FW Version = 01.1F.0118 Info : SWCLK/TCK = 1 SWDIO/TMS = 1 TDI = 1 TDO = 1 nTRST = 0 nRESET = 1 Info : CMSIS-DAP: Interface ready Info : clock speed 500 kHz Info : SWD IDCODE 0x0bc11477 Info : at91samd21g18.cpu: hardware has 4 breakpoints, 2 watchpoints target state: halted target halted due to debug-request, current mode: Thread xPSR: 0x21000000 pc: 0x0000fca6 psp: 0x20002408 GNU gdb (GNU Tools for ARM Embedded Processors) 7.8.0.20150604-cvs Copyright (C) 2014 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html> This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. Type \"show copying\" and \"show warranty\" for details. This GDB was configured as \"--host=x86_64-apple-darwin10 --target=arm-none-eabi\". Type \"show configuration\" for configuration details. For bug reporting instructions, please see: <http://www.gnu.org/software/gdb/bugs/>. Find the GDB manual and other documentation resources online at: <http://www.gnu.org/software/gdb/documentation/>. For help, type \"help\". Type \"apropos word\" to search for commands related to \"word\"... Reading symbols from ~/dev/myproj/bin/targets/arduino_blinky/app/apps/blinky/blinky.elf...(no debugging symbols found)...done. Info : accepting 'gdb' connection on tcp/3333 Info : SAMD MCU: SAMD21G18A (256KB Flash, 32KB RAM) 0x0000fca6 in os_tick_idle () target state: halted target halted due to debug-request, current mode: Thread xPSR: 0x21000000 pc: 0x000000b8 msp: 0x20008000 target state: halted target halted due to debug-request, current mode: Thread xPSR: 0x21000000 pc: 0x000000b8 msp: 0x20008000 (gdb) r The \"remote\" target does not support \"run\". Try \"help target\" or \"continue\". (gdb) c Continuing. NOTE: The 1.0.0 is the version number to assign to the image. You may assign an arbitrary version number. If you are not providing remote upgrade, and are just developing locally, you can provide 1.0.0 for every image version. If you want the image to run without the debugger connected, simply quit the debugger and restart the board. The image you programmed will come up and run on the Arduino on the next boot! You should see the LED blink!","title":"Run the Blinky Application"},{"location":"os/tutorials/blehci_project/","text":"Use HCI access to NimBLE controller This tutorial explains how to use the example application blehci included in the NimBLE stack to talk to the Mynewt NimBLE controller via the Host Controller Interface. You may build the Mynewt image using a laptop running any OS of your choice - Mac, Linux, or Windows. The host used in this specific example is the BlueZ Bluetooth stack. Since BlueZ is a Bluetooth stack for Linux kernel-based family of operating system, the tutorial expects a computer running Linux OS and with BlueZ installed to talk to the board with the Mynewt image. Prerequisites Ensure that you meet the following prerequisites before continuing with one of the tutorials. Have Internet connectivity to fetch remote Mynewt components. Have a board with BLE radio that is supported by Mynewt. We will use an nRF52 Dev board in this tutorial. Have a USB TTL Serial Cable that supports hardware flow control such as ones found at http://www.ftdichip.com/Products/Cables/USBTTLSerial.htm to establish a serial USB connection between the board and the laptop. Install the newt tool and toolchains (See Basic Setup ). Install a BLE host such as BlueZ on a Linux machine to talk to the nrf52 board running Mynewt. Use sudo apt-get install bluez to install it on your Linux machine. Create a project Use the newt tool to create a new project directory containing a skeletal Mynewt framework. Change into the newly created directory. $ newt new blehciproj Downloading project skeleton from apache/incubator-mynewt-blinky... Installing skeleton in blehciproj ... Project blehciproj successfully created. $ cd mblehciproj $ newt install apache-mynewt-core Create targets You will create two targets - one for the bootloader, the other for the application. Then you will add the definitions for them. Note that you are using the example app blehci for the application target. Set the bsp correctly (nrf52pdk or nrf52dk depending on whether the board is the preview kit or the dev kit, respectively). $ newt target create nrf52_boot $ newt target set nrf52_boot app=@apache-mynewt-core/apps/boot $ newt target set nrf52_boot bsp=@apache-mynewt-core/hw/bsp/nrf52dk $ newt target set nrf52_boot build_profile=optimized $ newt target create myble2 $ newt target set myble2 bsp=@apache-mynewt-core/hw/bsp/nrf52dk $ newt target set myble2 app=@apache-mynewt-core/apps/blehci $ newt target set myble2 build_profile=optimized Check that the targets are defined correctly. $ newt target show targets/my_blinky_sim app=apps/blinky bsp=@apache-mynewt-core/hw/bsp/native build_profile=debug targets/myble2 app=@apache-mynewt-core/apps/blehci bsp=@apache-mynewt-core/hw/bsp/nrf52dk build_profile=optimized targets/nrf52_boot app=@apache-mynewt-core/apps/boot bsp=@apache-mynewt-core/hw/bsp/nrf52dk build_profile=optimized Build targets Then build the two targets. $ newt build nrf52_boot <snip> Linking ~/dev/blehciproj/bin/targets/nrf52_boot/app/apps/boot/boot.elf Target successfully built: targets/nrf52_boot $ newt build myble2 <snip> Linking ~/dev/blehciproj/bin/targets/myble2/app/apps/blehci/blehci.elf Target successfully built: targets/myble2 $ Create the app image Generate a signed application image for the myble2 target. The version number is arbitrary. $ newt create-image myble2 1.0.0 App image succesfully generated: ~/dev/blehciproj/bin/targets/myble2/app/apps/bletiny/bletiny.img Load the bootloader and the application image Make sure the USB connector is in place and the power LED on the board is lit. Use the Power ON/OFF switch to reset the board after loading the image. Load the bootloader: $ newt load nrf52_boot Loading bootloader $ Load the application image: $ newt load myble2 Loading app image into slot 1 $ Establish serial connection Attach a serial port to your board by connecting the USB TTL Serial Cable. This should create /dev/ttyUSB0 (or similar) on your machine. Note Certain Linux OS versions have been observed to detect the nrf52 board as a mass storage device and the console access doesn\u2019t work properly. In that case try powering the nrf52 board from your monitor or something other than your Linux computer/laptop when you set up the serial port for HCI communication. Open Bluetooth monitor btmon btmon is a BlueZ test tool to display all HCI commands and events in a human readable format. Start the btmon tool in a terminal window. $ sudo btmon [sudo] password for admin: Bluetooth monitor ver 5.37 Attach the blehci device to BlueZ In a different terminal, attach the blehci device to the BlueZ daemon (substitute the correct /dev filename for ttyUSB0). $ sudo btattach -B /dev/ttyUSB0 -S 1000000 Attaching BR/EDR controller to /dev/ttyUSB0 Switched line discipline from 0 to 15 Device index 1 attached The baud rate used to connect to the controller may be changed by overriding the default value of 1000000 in the net/nimble/transport/uart/syscfg.yml . Settings in the serial transport syscfg.yml file can be overridden by a higher priority package such as the application. So, for example, you may set the BLE_HCI_UART_BAUD to a different value in apps/blehci/syscfg.yml . If there is no CTS/RTS lines present in the test environment, flow control should be turned off. This can be done with -N option for btattach. Note: -N option came with BlueZ ver 5.44. Start btmgmt to send commands In a third terminal, start btmgmt. This tool allows you to send commands to the blehci controller. Use the index number that shows up when you btattach in the previous step. $ sudo btmgmt --index 1 [sudo] password for admin: Set your device address (you can substitute any static random address here). [hci1]# static-addr cc:11:11:11:11:11 Static address successfully set Initialize the controller. [hci1]# power on hci1 Set Powered complete, settings: powered le static-addr Begin scanning. [hci1]# find -l Discovery started hci1 type 6 discovering on hci1 dev_found: 58:EF:77:C8:8D:17 type LE Random rssi -78 flags 0x0000 AD flags 0x06 eir_len 23 <snip>","title":"BLE HCI interface"},{"location":"os/tutorials/blehci_project/#use-hci-access-to-nimble-controller","text":"This tutorial explains how to use the example application blehci included in the NimBLE stack to talk to the Mynewt NimBLE controller via the Host Controller Interface. You may build the Mynewt image using a laptop running any OS of your choice - Mac, Linux, or Windows. The host used in this specific example is the BlueZ Bluetooth stack. Since BlueZ is a Bluetooth stack for Linux kernel-based family of operating system, the tutorial expects a computer running Linux OS and with BlueZ installed to talk to the board with the Mynewt image.","title":"Use HCI access to NimBLE controller"},{"location":"os/tutorials/blehci_project/#prerequisites","text":"Ensure that you meet the following prerequisites before continuing with one of the tutorials. Have Internet connectivity to fetch remote Mynewt components. Have a board with BLE radio that is supported by Mynewt. We will use an nRF52 Dev board in this tutorial. Have a USB TTL Serial Cable that supports hardware flow control such as ones found at http://www.ftdichip.com/Products/Cables/USBTTLSerial.htm to establish a serial USB connection between the board and the laptop. Install the newt tool and toolchains (See Basic Setup ). Install a BLE host such as BlueZ on a Linux machine to talk to the nrf52 board running Mynewt. Use sudo apt-get install bluez to install it on your Linux machine.","title":"Prerequisites"},{"location":"os/tutorials/blehci_project/#create-a-project","text":"Use the newt tool to create a new project directory containing a skeletal Mynewt framework. Change into the newly created directory. $ newt new blehciproj Downloading project skeleton from apache/incubator-mynewt-blinky... Installing skeleton in blehciproj ... Project blehciproj successfully created. $ cd mblehciproj $ newt install apache-mynewt-core","title":"Create a project"},{"location":"os/tutorials/blehci_project/#create-targets","text":"You will create two targets - one for the bootloader, the other for the application. Then you will add the definitions for them. Note that you are using the example app blehci for the application target. Set the bsp correctly (nrf52pdk or nrf52dk depending on whether the board is the preview kit or the dev kit, respectively). $ newt target create nrf52_boot $ newt target set nrf52_boot app=@apache-mynewt-core/apps/boot $ newt target set nrf52_boot bsp=@apache-mynewt-core/hw/bsp/nrf52dk $ newt target set nrf52_boot build_profile=optimized $ newt target create myble2 $ newt target set myble2 bsp=@apache-mynewt-core/hw/bsp/nrf52dk $ newt target set myble2 app=@apache-mynewt-core/apps/blehci $ newt target set myble2 build_profile=optimized Check that the targets are defined correctly. $ newt target show targets/my_blinky_sim app=apps/blinky bsp=@apache-mynewt-core/hw/bsp/native build_profile=debug targets/myble2 app=@apache-mynewt-core/apps/blehci bsp=@apache-mynewt-core/hw/bsp/nrf52dk build_profile=optimized targets/nrf52_boot app=@apache-mynewt-core/apps/boot bsp=@apache-mynewt-core/hw/bsp/nrf52dk build_profile=optimized","title":"Create targets"},{"location":"os/tutorials/blehci_project/#build-targets","text":"Then build the two targets. $ newt build nrf52_boot <snip> Linking ~/dev/blehciproj/bin/targets/nrf52_boot/app/apps/boot/boot.elf Target successfully built: targets/nrf52_boot $ newt build myble2 <snip> Linking ~/dev/blehciproj/bin/targets/myble2/app/apps/blehci/blehci.elf Target successfully built: targets/myble2 $","title":"Build targets"},{"location":"os/tutorials/blehci_project/#create-the-app-image","text":"Generate a signed application image for the myble2 target. The version number is arbitrary. $ newt create-image myble2 1.0.0 App image succesfully generated: ~/dev/blehciproj/bin/targets/myble2/app/apps/bletiny/bletiny.img","title":"Create the app image"},{"location":"os/tutorials/blehci_project/#load-the-bootloader-and-the-application-image","text":"Make sure the USB connector is in place and the power LED on the board is lit. Use the Power ON/OFF switch to reset the board after loading the image. Load the bootloader: $ newt load nrf52_boot Loading bootloader $ Load the application image: $ newt load myble2 Loading app image into slot 1 $","title":"Load the bootloader and the application image"},{"location":"os/tutorials/blehci_project/#establish-serial-connection","text":"Attach a serial port to your board by connecting the USB TTL Serial Cable. This should create /dev/ttyUSB0 (or similar) on your machine. Note Certain Linux OS versions have been observed to detect the nrf52 board as a mass storage device and the console access doesn\u2019t work properly. In that case try powering the nrf52 board from your monitor or something other than your Linux computer/laptop when you set up the serial port for HCI communication.","title":"Establish serial connection"},{"location":"os/tutorials/blehci_project/#open-bluetooth-monitor-btmon","text":"btmon is a BlueZ test tool to display all HCI commands and events in a human readable format. Start the btmon tool in a terminal window. $ sudo btmon [sudo] password for admin: Bluetooth monitor ver 5.37","title":"Open Bluetooth monitor btmon"},{"location":"os/tutorials/blehci_project/#attach-the-blehci-device-to-bluez","text":"In a different terminal, attach the blehci device to the BlueZ daemon (substitute the correct /dev filename for ttyUSB0). $ sudo btattach -B /dev/ttyUSB0 -S 1000000 Attaching BR/EDR controller to /dev/ttyUSB0 Switched line discipline from 0 to 15 Device index 1 attached The baud rate used to connect to the controller may be changed by overriding the default value of 1000000 in the net/nimble/transport/uart/syscfg.yml . Settings in the serial transport syscfg.yml file can be overridden by a higher priority package such as the application. So, for example, you may set the BLE_HCI_UART_BAUD to a different value in apps/blehci/syscfg.yml . If there is no CTS/RTS lines present in the test environment, flow control should be turned off. This can be done with -N option for btattach. Note: -N option came with BlueZ ver 5.44.","title":"Attach the blehci device to BlueZ"},{"location":"os/tutorials/blehci_project/#start-btmgmt-to-send-commands","text":"In a third terminal, start btmgmt. This tool allows you to send commands to the blehci controller. Use the index number that shows up when you btattach in the previous step. $ sudo btmgmt --index 1 [sudo] password for admin: Set your device address (you can substitute any static random address here). [hci1]# static-addr cc:11:11:11:11:11 Static address successfully set Initialize the controller. [hci1]# power on hci1 Set Powered complete, settings: powered le static-addr Begin scanning. [hci1]# find -l Discovery started hci1 type 6 discovering on hci1 dev_found: 58:EF:77:C8:8D:17 type LE Random rssi -78 flags 0x0000 AD flags 0x06 eir_len 23 <snip>","title":"Start btmgmt to send commands"},{"location":"os/tutorials/bletiny_project/","text":"Check stats for a BLE Application the NRF52 Board This tutorial explains how to run an example BLE app on a board and command it to scan and spew some stats. The stats will be seen over a serial port, not a BLE wireless connection. Prerequisites Ensure that you have met the following prerequisites before continuing with this tutorial: Have Internet connectivity to fetch remote Mynewt components. Have a board with BLE radio that is supported by Mynewt. We will use an nRF52 Dev board in this tutorial. Have a cable to establish a serial USB connection between the board and the laptop Install the newt tool and toolchains (See Basic Setup ). Install the Segger JLINK package to load your project on the board. Create a project Use the newt tool to create a new project directory containing a skeletal Mynewt framework. Change into the newly created directory. $ newt new myproj Downloading project skeleton from apache/incubator-mynewt-blinky... Installing skeleton in myproj... Project myproj successfully created. $ cd myproj $ newt install Create targets You will create two targets - one for the bootloader, the other for the application. $ newt target create myble Target targets/myble successfully created $ newt target create nrf52_boot Target targets/myble successfully created $ newt target show targets/my_blinky_sim app=apps/blinky bsp=@apache-mynewt-core/hw/bsp/native build_profile=debug targets/myble targets/nrf52_boot Define the targets further. Note that you are using the example app bletiny for the application target. Set the bsp NOTE: The preview version, nrf52pdk, is no longer supported. If you do not see PCA100040 on the top of your board, you have a preview version of the board and will need to upgrade your developer board before continuing. $ newt target set myble bsp=@apache-mynewt-core/hw/bsp/nrf52dk Target targets/myble successfully set target.bsp to @apache-mynewt-core/hw/bsp/nrf52dk $ newt target set myble app=@apache-mynewt-core/apps/bletiny Target targets/myble successfully set target.app to @apache-mynewt-core/apps/bletiny $ newt target set myble build_profile=optimized Target targets/myble successfully set target.build_profile to optimized Use the same newt target set command to set the following definition for the bootloader target -- again, make sure you use the correct value for the bsp based on which version of the board you have.. targets/nrf52_boot app=@apache-mynewt-core/apps/boot bsp=@apache-mynewt-core/hw/bsp/nrf52dk build_profile=optimized You should have the following targets by the end of this step. $ newt target show targets/my_blinky_sim app=apps/blinky bsp=@apache-mynewt-core/hw/bsp/native build_profile=debug targets/myble app=@apache-mynewt-core/apps/bletiny bsp=@apache-mynewt-core/hw/bsp/nrf52dk build_profile=optimized targets/nrf52_boot app=@apache-mynewt-core/apps/boot bsp=@apache-mynewt-core/hw/bsp/nrf52dk build_profile=optimized Since we're interested in seeing the stats, we'll need to enable the stats module for the target. By default, the stats module is not enabled, so we will have to override the default behavior. To do this, you'll need to create a configuration file syscfg.yml in the app directory. from the target definition above, you can see that the app is in apache-mynewt-core/apps/bletiny so that is where you'll put your configuration file. # Package: apps/bletiny syscfg.vals: SHELL_TASK: 1 STATS_NAMES: 1 STATS_CLI: 1 The first configuration value turns on the Shell Task, and we'll need this to get to the shell. The next 2 enable the names for the various stats, and then turns on the stats CLI option. Build targets Then build the two targets. Run the newt build nrf52_boot command to build the bootloader: Building target targets/nrf52_boot Compiling repos/apache-mynewt-core/boot/bootutil/src/image_ec.c Compiling repos/apache-mynewt-core/boot/bootutil/src/image_ec256.c Compiling repos/apache-mynewt-core/boot/bootutil/src/image_rsa.c Compiling repos/apache-mynewt-core/boot/bootutil/src/bootutil_misc.c Compiling repos/apache-mynewt-core/boot/bootutil/src/loader.c Compiling repos/apache-mynewt-core/apps/boot/src/boot.c Archiving sys_sysinit.a Archiving util_mem.a Linking ~/myproj/bin/targets/nrf52_boot/app/apps/boot/boot.elf Target successfully built: targets/nrf52_boot Run the newt build myble command to build the bletiny application: newt build myble Building target targets/myble Compiling repos/apache-mynewt-core/encoding/base64/src/base64.c Compiling repos/apache-mynewt-core/encoding/base64/src/hex.c Compiling repos/apache-mynewt-core/hw/bsp/nrf52dk/src/hal_bsp.c Compiling repos/apache-mynewt-core/apps/bletiny/src/parse.c Compiling repos/apache-mynewt-core/apps/bletiny/src/misc.c Compiling repos/apache-mynewt-core/apps/bletiny/src/gatt_svr.c Compiling repos/apache-mynewt-core/apps/bletiny/src/cmd.c Compiling repos/apache-mynewt-core/apps/bletiny/src/main.c Archiving util_mem.a Linking ~/dev/myproj/bin/targets/myble/app/apps/bletiny/bletiny.elf Target successfully built: targets/myble Create the app image Run the newt create-image myble 1.0.0 command to generate a signed application image for the myble target. The version number is arbitrary. $newt create-image myble 1.0.0 Compiling bin/targets/myble/generated/src/myble-sysinit-app.c Archiving myble-sysinit-app.a Linking ~/dev/myproj/bin/targets/myble/app/apps/bletiny/bletiny.elf App image succesfully generated: ~/dev/myproj/bin/targets/myble/app/apps/bletiny/bletiny.img Load the image Make sure the USB connector is in place and the power LED on the board is lit. Use the Power ON/OFF switch to reset the board after loading the image. $ newt load nrf52_boot $ newt load myble Establish serial connection You will now look for some BLE related stats over a serial connection and see the radio is actually working. If you haven't done so already, make sure you're familiar with the Serial Port Setup and Configuration section. Once you have a connection set up, you can connect to your device as follows: On Mac OS and Linux platforms, you can run minicom -D /dev/tty.usbserial-<port> -b 115200 to connect to the console of your app. Note that on Linux, the format of the port name is /dev/ttyUSB<N> , where N is a number. On Windows, you can run PuTTY to connect to the device. If you located your port from a MinGW terminal, the port name format is /dev/ttyS<N> , where N is a number. You must map the port name to a Windows COM port: /dev/ttyS<N> maps to COM<N+1> . For example, /dev/ttyS2 maps to COM3 . You can also use the Windows Device Manager to locate the COM port number. This tutorial uses minicom. When the Minicom screen comes up, type in ? Welcome to minicom 2.7 OPTIONS: Compiled on Mar 18 2016, 04:59:47. Port /dev/tty.usbserial-1a12, 21:24:09 Press Meta-Z for help on special keys ? 7471:Commands: 7471: stat echo ? prompt ticks tasks 7474: mempools date b If you'd like a shell prompt, try the prompt command. prompt 14025:Usage: prompt [set|show] [prompt_char] prompt set > 15086:Prompt set to: > 15086:Usage: prompt [set|show] [prompt_char] 15087: > You'll notice that there is an ever-increasing counter before the prompt (and before any output to the terminal). This is just a counter kept by the MCU. Note : If you want to have a shell prompt by default, simply add the line: CONSOLE_PROMPT: 1 to your syscfg.yml file and it will be turned on by default. Try the tasks command. > tasks Tasks: 46682: task pri tid runtime csw stksz stkuse lcheck ncheck fg 46684: idle 255 0 46683 99 64 31 0 0 0 46686: main 127 1 1 29 512 156 0 0 0 46688: ble_ll 0 2 0 12 80 58 0 0 0 46691: > Try specifying a BLE related stat, for example ble_ll . You should see some HCI (Host Controller Interface) command counts. 113136: > stat ble_ll hci_cmds: 11 155545:hci_cmd_errs: 0 155545:hci_events_sent: 11 155547:bad_ll_state: 0 155547:bad_acl_hdr: 0 155548:no_bufs: 0 155548:rx_adv_pdu_crc_ok: 0 155549:rx_adv_pdu_crc_err: 0 155550:rx_adv_bytes_crc_ok: 0 155551:rx_adv_bytes_crc_err: 0 155552:rx_data_pdu_crc_ok: 0 ... 155564:scan_req_txf: 0 155565:scan_req_txg: 0 155565:scan_rsp_txg: 0 155566: > For a more exciting output, try scanning your surroundings for BLE advertisements. The HCI command shown below specifies a scan duration in ms, scan to passive, and no duplicates. You should see some scan data flying by! b scan dur=10000 passive=1 nodups=1 37266:[ts=291140616ssb, mod=4 level=1] GAP procedure initiated: discovery; own_as 37641: 38256:received advertisement; event_type=0 rssi=-48 addr_type=1 addr=59:cc:3d:a3: 38261: flags=0x1a: 38261: General discoverable mode 38262: uuids16(complete)=0x1802 38263: name(complete)=Find Me 38264: 38551:scanning finished If you're still not seeing any output from the device, try running the debugger and see if you are seeing the program execute properly. $newt debug myble [~/dev/myproj/repos/apache-mynewt-core/hw/bsp/nrf52dk/nrf52dk_debug.sh ~/dev/myproj/repos/apache-mynewt-core/hw/bsp/nrf52dk ~/dev/wanda/dev/myproj/bin/targets/myble/app/apps/bletiny/bletiny] ~/dev/myproj/repos/apache-mynewt-core/hw/scripts/common.sh: line 38: [: =: unary operator expected Debugging ~/dev/myproj/bin/targets/myble/app/apps/bletiny/bletiny.elf GNU gdb (GNU Tools for ARM Embedded Processors) 7.8.0.20150604-cvs Copyright (C) 2014 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html> This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. Type \"show copying\" and \"show warranty\" for details. This GDB was configured as \"--host=x86_64-apple-darwin10 --target=arm-none-eabi\". Type \"show configuration\" for configuration details. For bug reporting instructions, please see: <http://www.gnu.org/software/gdb/bugs/>. Find the GDB manual and other documentation resources online at: <http://www.gnu.org/software/gdb/documentation/>. For help, type \"help\". Type \"apropos word\" to search for commands related to \"word\"... Reading symbols from ~/dev/myproj/bin/targets/myble/app/apps/bletiny/bletiny.elf...done. os_tick_idle (ticks=1920) at repos/apache-mynewt-core/hw/mcu/nordic/nrf52xxx/src/hal_os_tick.c:200 200 if (ticks > 0) { (gdb) monitor reset Resetting target (gdb) c Continuing. ^C Program received signal SIGTRAP, Trace/breakpoint trap. os_tick_idle (ticks=1907) at repos/apache-mynewt-core/hw/mcu/nordic/nrf52xxx/src/hal_os_tick.c:200 200 if (ticks > 0) { (gdb) p g_os_time $1 = 13 (gdb) c Continuing. ^C Program received signal SIGTRAP, Trace/breakpoint trap. os_tick_idle (ticks=1920) at repos/apache-mynewt-core/hw/mcu/nordic/nrf52xxx/src/hal_os_tick.c:200 200 if (ticks > 0) { (gdb) p g_os_time $2 = 6611 (gdb) You should see the g_os_time advancing as above, as each os time tick is 1ms. If the system ticks aren't advancing, then nothing's actually running.","title":"BLE app to check stats via console"},{"location":"os/tutorials/bletiny_project/#check-stats-for-a-ble-application-the-nrf52-board","text":"This tutorial explains how to run an example BLE app on a board and command it to scan and spew some stats. The stats will be seen over a serial port, not a BLE wireless connection.","title":"Check stats for a BLE Application the NRF52 Board"},{"location":"os/tutorials/bletiny_project/#prerequisites","text":"Ensure that you have met the following prerequisites before continuing with this tutorial: Have Internet connectivity to fetch remote Mynewt components. Have a board with BLE radio that is supported by Mynewt. We will use an nRF52 Dev board in this tutorial. Have a cable to establish a serial USB connection between the board and the laptop Install the newt tool and toolchains (See Basic Setup ). Install the Segger JLINK package to load your project on the board.","title":"Prerequisites"},{"location":"os/tutorials/bletiny_project/#create-a-project","text":"Use the newt tool to create a new project directory containing a skeletal Mynewt framework. Change into the newly created directory. $ newt new myproj Downloading project skeleton from apache/incubator-mynewt-blinky... Installing skeleton in myproj... Project myproj successfully created. $ cd myproj $ newt install","title":"Create a project"},{"location":"os/tutorials/bletiny_project/#create-targets","text":"You will create two targets - one for the bootloader, the other for the application. $ newt target create myble Target targets/myble successfully created $ newt target create nrf52_boot Target targets/myble successfully created $ newt target show targets/my_blinky_sim app=apps/blinky bsp=@apache-mynewt-core/hw/bsp/native build_profile=debug targets/myble targets/nrf52_boot Define the targets further. Note that you are using the example app bletiny for the application target. Set the bsp NOTE: The preview version, nrf52pdk, is no longer supported. If you do not see PCA100040 on the top of your board, you have a preview version of the board and will need to upgrade your developer board before continuing. $ newt target set myble bsp=@apache-mynewt-core/hw/bsp/nrf52dk Target targets/myble successfully set target.bsp to @apache-mynewt-core/hw/bsp/nrf52dk $ newt target set myble app=@apache-mynewt-core/apps/bletiny Target targets/myble successfully set target.app to @apache-mynewt-core/apps/bletiny $ newt target set myble build_profile=optimized Target targets/myble successfully set target.build_profile to optimized Use the same newt target set command to set the following definition for the bootloader target -- again, make sure you use the correct value for the bsp based on which version of the board you have.. targets/nrf52_boot app=@apache-mynewt-core/apps/boot bsp=@apache-mynewt-core/hw/bsp/nrf52dk build_profile=optimized You should have the following targets by the end of this step. $ newt target show targets/my_blinky_sim app=apps/blinky bsp=@apache-mynewt-core/hw/bsp/native build_profile=debug targets/myble app=@apache-mynewt-core/apps/bletiny bsp=@apache-mynewt-core/hw/bsp/nrf52dk build_profile=optimized targets/nrf52_boot app=@apache-mynewt-core/apps/boot bsp=@apache-mynewt-core/hw/bsp/nrf52dk build_profile=optimized Since we're interested in seeing the stats, we'll need to enable the stats module for the target. By default, the stats module is not enabled, so we will have to override the default behavior. To do this, you'll need to create a configuration file syscfg.yml in the app directory. from the target definition above, you can see that the app is in apache-mynewt-core/apps/bletiny so that is where you'll put your configuration file. # Package: apps/bletiny syscfg.vals: SHELL_TASK: 1 STATS_NAMES: 1 STATS_CLI: 1 The first configuration value turns on the Shell Task, and we'll need this to get to the shell. The next 2 enable the names for the various stats, and then turns on the stats CLI option.","title":"Create targets"},{"location":"os/tutorials/bletiny_project/#build-targets","text":"Then build the two targets. Run the newt build nrf52_boot command to build the bootloader: Building target targets/nrf52_boot Compiling repos/apache-mynewt-core/boot/bootutil/src/image_ec.c Compiling repos/apache-mynewt-core/boot/bootutil/src/image_ec256.c Compiling repos/apache-mynewt-core/boot/bootutil/src/image_rsa.c Compiling repos/apache-mynewt-core/boot/bootutil/src/bootutil_misc.c Compiling repos/apache-mynewt-core/boot/bootutil/src/loader.c Compiling repos/apache-mynewt-core/apps/boot/src/boot.c Archiving sys_sysinit.a Archiving util_mem.a Linking ~/myproj/bin/targets/nrf52_boot/app/apps/boot/boot.elf Target successfully built: targets/nrf52_boot Run the newt build myble command to build the bletiny application: newt build myble Building target targets/myble Compiling repos/apache-mynewt-core/encoding/base64/src/base64.c Compiling repos/apache-mynewt-core/encoding/base64/src/hex.c Compiling repos/apache-mynewt-core/hw/bsp/nrf52dk/src/hal_bsp.c Compiling repos/apache-mynewt-core/apps/bletiny/src/parse.c Compiling repos/apache-mynewt-core/apps/bletiny/src/misc.c Compiling repos/apache-mynewt-core/apps/bletiny/src/gatt_svr.c Compiling repos/apache-mynewt-core/apps/bletiny/src/cmd.c Compiling repos/apache-mynewt-core/apps/bletiny/src/main.c Archiving util_mem.a Linking ~/dev/myproj/bin/targets/myble/app/apps/bletiny/bletiny.elf Target successfully built: targets/myble","title":"Build targets"},{"location":"os/tutorials/bletiny_project/#create-the-app-image","text":"Run the newt create-image myble 1.0.0 command to generate a signed application image for the myble target. The version number is arbitrary. $newt create-image myble 1.0.0 Compiling bin/targets/myble/generated/src/myble-sysinit-app.c Archiving myble-sysinit-app.a Linking ~/dev/myproj/bin/targets/myble/app/apps/bletiny/bletiny.elf App image succesfully generated: ~/dev/myproj/bin/targets/myble/app/apps/bletiny/bletiny.img","title":"Create the app image"},{"location":"os/tutorials/bletiny_project/#load-the-image","text":"Make sure the USB connector is in place and the power LED on the board is lit. Use the Power ON/OFF switch to reset the board after loading the image. $ newt load nrf52_boot $ newt load myble","title":"Load the image"},{"location":"os/tutorials/bletiny_project/#establish-serial-connection","text":"You will now look for some BLE related stats over a serial connection and see the radio is actually working. If you haven't done so already, make sure you're familiar with the Serial Port Setup and Configuration section. Once you have a connection set up, you can connect to your device as follows: On Mac OS and Linux platforms, you can run minicom -D /dev/tty.usbserial-<port> -b 115200 to connect to the console of your app. Note that on Linux, the format of the port name is /dev/ttyUSB<N> , where N is a number. On Windows, you can run PuTTY to connect to the device. If you located your port from a MinGW terminal, the port name format is /dev/ttyS<N> , where N is a number. You must map the port name to a Windows COM port: /dev/ttyS<N> maps to COM<N+1> . For example, /dev/ttyS2 maps to COM3 . You can also use the Windows Device Manager to locate the COM port number. This tutorial uses minicom. When the Minicom screen comes up, type in ? Welcome to minicom 2.7 OPTIONS: Compiled on Mar 18 2016, 04:59:47. Port /dev/tty.usbserial-1a12, 21:24:09 Press Meta-Z for help on special keys ? 7471:Commands: 7471: stat echo ? prompt ticks tasks 7474: mempools date b If you'd like a shell prompt, try the prompt command. prompt 14025:Usage: prompt [set|show] [prompt_char] prompt set > 15086:Prompt set to: > 15086:Usage: prompt [set|show] [prompt_char] 15087: > You'll notice that there is an ever-increasing counter before the prompt (and before any output to the terminal). This is just a counter kept by the MCU. Note : If you want to have a shell prompt by default, simply add the line: CONSOLE_PROMPT: 1 to your syscfg.yml file and it will be turned on by default. Try the tasks command. > tasks Tasks: 46682: task pri tid runtime csw stksz stkuse lcheck ncheck fg 46684: idle 255 0 46683 99 64 31 0 0 0 46686: main 127 1 1 29 512 156 0 0 0 46688: ble_ll 0 2 0 12 80 58 0 0 0 46691: > Try specifying a BLE related stat, for example ble_ll . You should see some HCI (Host Controller Interface) command counts. 113136: > stat ble_ll hci_cmds: 11 155545:hci_cmd_errs: 0 155545:hci_events_sent: 11 155547:bad_ll_state: 0 155547:bad_acl_hdr: 0 155548:no_bufs: 0 155548:rx_adv_pdu_crc_ok: 0 155549:rx_adv_pdu_crc_err: 0 155550:rx_adv_bytes_crc_ok: 0 155551:rx_adv_bytes_crc_err: 0 155552:rx_data_pdu_crc_ok: 0 ... 155564:scan_req_txf: 0 155565:scan_req_txg: 0 155565:scan_rsp_txg: 0 155566: > For a more exciting output, try scanning your surroundings for BLE advertisements. The HCI command shown below specifies a scan duration in ms, scan to passive, and no duplicates. You should see some scan data flying by! b scan dur=10000 passive=1 nodups=1 37266:[ts=291140616ssb, mod=4 level=1] GAP procedure initiated: discovery; own_as 37641: 38256:received advertisement; event_type=0 rssi=-48 addr_type=1 addr=59:cc:3d:a3: 38261: flags=0x1a: 38261: General discoverable mode 38262: uuids16(complete)=0x1802 38263: name(complete)=Find Me 38264: 38551:scanning finished If you're still not seeing any output from the device, try running the debugger and see if you are seeing the program execute properly. $newt debug myble [~/dev/myproj/repos/apache-mynewt-core/hw/bsp/nrf52dk/nrf52dk_debug.sh ~/dev/myproj/repos/apache-mynewt-core/hw/bsp/nrf52dk ~/dev/wanda/dev/myproj/bin/targets/myble/app/apps/bletiny/bletiny] ~/dev/myproj/repos/apache-mynewt-core/hw/scripts/common.sh: line 38: [: =: unary operator expected Debugging ~/dev/myproj/bin/targets/myble/app/apps/bletiny/bletiny.elf GNU gdb (GNU Tools for ARM Embedded Processors) 7.8.0.20150604-cvs Copyright (C) 2014 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html> This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. Type \"show copying\" and \"show warranty\" for details. This GDB was configured as \"--host=x86_64-apple-darwin10 --target=arm-none-eabi\". Type \"show configuration\" for configuration details. For bug reporting instructions, please see: <http://www.gnu.org/software/gdb/bugs/>. Find the GDB manual and other documentation resources online at: <http://www.gnu.org/software/gdb/documentation/>. For help, type \"help\". Type \"apropos word\" to search for commands related to \"word\"... Reading symbols from ~/dev/myproj/bin/targets/myble/app/apps/bletiny/bletiny.elf...done. os_tick_idle (ticks=1920) at repos/apache-mynewt-core/hw/mcu/nordic/nrf52xxx/src/hal_os_tick.c:200 200 if (ticks > 0) { (gdb) monitor reset Resetting target (gdb) c Continuing. ^C Program received signal SIGTRAP, Trace/breakpoint trap. os_tick_idle (ticks=1907) at repos/apache-mynewt-core/hw/mcu/nordic/nrf52xxx/src/hal_os_tick.c:200 200 if (ticks > 0) { (gdb) p g_os_time $1 = 13 (gdb) c Continuing. ^C Program received signal SIGTRAP, Trace/breakpoint trap. os_tick_idle (ticks=1920) at repos/apache-mynewt-core/hw/mcu/nordic/nrf52xxx/src/hal_os_tick.c:200 200 if (ticks > 0) { (gdb) p g_os_time $2 = 6611 (gdb) You should see the g_os_time advancing as above, as each os time tick is 1ms. If the system ticks aren't advancing, then nothing's actually running.","title":"Establish serial connection"},{"location":"os/tutorials/blinky/","text":"Blinky, your \"Hello World!\" on a Target Board The set of Blinky tutorials show you how to create, build, and run a \"Hello World\" application that blinks a LED on the various target boards that Mynewt supports. The tutorials use the same Blinky application from the Creating Your First Project tutorial. Objective Learn how to use packages from a default application repository of Mynewt to build your first Hello World application (Blinky) on a target board. Once built using the newt tool, this application will blink a LED light on the target board. Available Tutorials Tutorials are available for the following boards: Blinky on an Arduino Zero Blinky on an Arduino Primo Blinky on an Olimex Blinky on a nRF52 Blinky on a RedBear Nano 2 Blinky on a STM32F4-Discovery We also have a tutorial that shows you how to add Console and Shell to the Blinky Application . Prerequisites Ensure that you meet the following prerequisites before continuing with one of the tutorials. Have Internet connectivity to fetch remote Mynewt components. Have a computer to build a Mynewt application and connect to the board over USB. Have a Micro-USB cable to connect the board and the computer. Install the newt tool and toolchains (See Basic Setup ). Read the Mynewt OS Concepts section. Create a project space (directory structure) and populate it with the core code repository (apache-mynewt-core) or know how to as explained in Creating Your First Project . Overview of Steps These are the general steps to create, load and run the Blinky application on your board: Create a project. Define the bootloader and Blinky application targets for the board. Build the bootloader target. Build the Blinky application target and create an application image. Connect to the board. Load the bootloader onto the board. Load the Blinky application image onto the board. See the LED on your board blink. After you try the Blinky application on your boards, checkout out other tutorials to enable additional functionality such as remote comms on the current board. If you have BLE (Bluetooth Low Energy) chip (e.g. nRF52) on your board, you can try turning it into an iBeacon or Eddystone Beacon ! If you see anything missing or want to send us feedback, please sign up for appropriate mailing lists on our Community Page .","title":"toc"},{"location":"os/tutorials/blinky/#blinky-your-hello-world-on-a-target-board","text":"The set of Blinky tutorials show you how to create, build, and run a \"Hello World\" application that blinks a LED on the various target boards that Mynewt supports. The tutorials use the same Blinky application from the Creating Your First Project tutorial.","title":"Blinky, your \"Hello World!\" on a Target Board"},{"location":"os/tutorials/blinky/#objective","text":"Learn how to use packages from a default application repository of Mynewt to build your first Hello World application (Blinky) on a target board. Once built using the newt tool, this application will blink a LED light on the target board.","title":"Objective"},{"location":"os/tutorials/blinky/#available-tutorials","text":"Tutorials are available for the following boards: Blinky on an Arduino Zero Blinky on an Arduino Primo Blinky on an Olimex Blinky on a nRF52 Blinky on a RedBear Nano 2 Blinky on a STM32F4-Discovery We also have a tutorial that shows you how to add Console and Shell to the Blinky Application .","title":"Available Tutorials"},{"location":"os/tutorials/blinky/#prerequisites","text":"Ensure that you meet the following prerequisites before continuing with one of the tutorials. Have Internet connectivity to fetch remote Mynewt components. Have a computer to build a Mynewt application and connect to the board over USB. Have a Micro-USB cable to connect the board and the computer. Install the newt tool and toolchains (See Basic Setup ). Read the Mynewt OS Concepts section. Create a project space (directory structure) and populate it with the core code repository (apache-mynewt-core) or know how to as explained in Creating Your First Project .","title":"Prerequisites"},{"location":"os/tutorials/blinky/#overview-of-steps","text":"These are the general steps to create, load and run the Blinky application on your board: Create a project. Define the bootloader and Blinky application targets for the board. Build the bootloader target. Build the Blinky application target and create an application image. Connect to the board. Load the bootloader onto the board. Load the Blinky application image onto the board. See the LED on your board blink. After you try the Blinky application on your boards, checkout out other tutorials to enable additional functionality such as remote comms on the current board. If you have BLE (Bluetooth Low Energy) chip (e.g. nRF52) on your board, you can try turning it into an iBeacon or Eddystone Beacon ! If you see anything missing or want to send us feedback, please sign up for appropriate mailing lists on our Community Page .","title":"Overview of Steps"},{"location":"os/tutorials/blinky_console/","text":"Enabling The Console and Shell for Blinky This tutorial shows you how to add the Console and Shell to the Blinky application and interact with it over a serial line connection. Prerequisites Work through one of the Blinky Tutorials to create and build a Blinky application for one of the boards. Have a serial setup . Use an Existing Project Since all we're doing is adding the shell and console capability to blinky, we assume that you have worked through at least some of the other tutorials, and have an existing project. For this example, we'll be modifying the blinky on nrf52 project to enable the shell and console connectivity. You can use blinky on a different board. Modify the Dependencies and Configuration Add the following dependencies to your application target's pkg.yml file: pkg.deps: - \"@apache-mynewt-core/sys/console/full\" - \"@apache-mynewt-core/sys/shell\" - \"@apache-mynewt-core/sys/sysinit\" This lets the newt system know that it needs to pull in the code for the console and the shell. Modify the system configuration settings to enable Shell and Console ticks and prompt. Add the following to your application target's syscfg.yml file: syscfg.vals: # Enable the shell task. SHELL_TASK: 1 # Enable Console OS Ticks CONSOLE_TICKS: 1 # Enable Console Prompt CONSOLE_PROMPT: 1 Use the OS Default Event Queue to Process Blinky Timer and Shell Events Mynewt creates a main task that executes the application main() function. It also creates an OS default event queue that packages can use to queue their events. Shell uses the OS default event queue for Shell events, and main() can process the events in the context of the main task. Blinky's main.c is very simple. It only has a main() function that executes an infinite loop to toggle the LED and sleep for one second. We will modify blinky: To use os_callout to generate a timer event every one second instead of sleeping. The timer events are added to the OS default event queue. To process events from the OS default event queue inside the infinite loop in main() . This allows the main task to process both Shell events and the timer events to toggle the LED from the OS default event queue. Modify main.c Initialize a os_callout timer and move the toggle code from the while loop in main() to the event callback function. Add the following code above the main() function: /* The timer callout */ static struct os_callout blinky_callout ; /* * Event callback function for timer events. It toggles the led pin. */ static void timer_ev_cb ( struct os_event *ev ) { assert ( ev != NULL ); ++g_task1_loops ; hal_gpio_toggle ( g_led_pin ); os_callout_reset ( &blinky_callout , OS_TICKS_PER_SEC ); } static void init_timer ( void ) { /* * Initialize the callout for a timer event. */ os_callout_init ( &blinky_callout , os_eventq_dflt_get (), timer_ev_cb , NULL ); os_callout_reset ( &blinky_callout , OS_TICKS_PER_SEC ); } In main() , add the call to the init_timer() function before the while loop and modify the while loop to process events from the OS default event queue: main ( int argc , char **argv ) { int rc ; #ifdef ARCH_sim mcu_sim_parse_args ( argc , argv ); #endif sysinit (); g_led_pin = LED_BLINK_PIN ; hal_gpio_init_out ( g_led_pin , 1 ); init_timer (); while ( 1 ) { os_eventq_run ( os_eventq_dflt_get ()); } assert ( 0 ) return rc ; } Build the Blinky Application Target We're not going to build the bootloader here since we are assuming that you have already built and loaded it during previous tutorials. Run the newt build nrf52_blinky command to build the Blinky application: $ newt build nrf52_blinky ... Archiving util_mem.a Linking ~/dev/myproj/bin/targets/nrf52_blinky/app/apps/blinky/blinky.elf Target successfully built: targets/nrf52_blinky Sign and Create the Blinky Application Image Run the newt create-image nrf52_blinky 1.0.0 command to create and sign the application image. You may assign an arbitrary version (e.g. 1.0.0) to the image. $ newt create-image nrf52_blinky 1.0.0 App image succesfully generated: ~/dev/myproj/bin/targets/nrf52_blinky/app/apps/blinky/blinky.img Load the Image Make sure the USB connector is in place and the power LED on the board is lit. Use the Power ON/OFF switch to reset the board after loading the image. Run the newt load nrf52_blinky command to load the Blinky application image onto the board. $ newt load nrf52_blinky Loading app image into slot 1 Set Up a Serial Connection You'll need a Serial connection to see the output of your program. You can reference the Serial Port Setup Tutorial for more information on setting up your serial communication. Communicate with the Application Once you have a connection set up, you can connect to your device as follows: On Mac OS and Linux platforms, you can run minicom -D /dev/tty.usbserial-<port> -b 115200 to connect to the console of your app. Note that on Linux, the format of the port name is /dev/ttyUSB<N> , where N is a number. On Windows, you can use a terminal application such as PuTTY to connect to the device. If you located your port from a MinGW terminal, the port name format is /dev/ttyS<N> , where N is a number. You must map the port name to a Windows COM port: /dev/ttyS<N> maps to COM<N+1> . For example, /dev/ttyS2 maps to COM3 . You can also use the Windows Device Manager to locate the COM port. To test and make sure that the Shell is running, first just hit : 3534: > You can try some commands: 3609: > ? Commands: 8841: echo ? prompt ticks tasks mempools 8843: date b 8844: > ticks off Console Ticks off > prompt off Prompt now off. ticks on 33383: Console Ticks on 33568: prompt on 39108: Prompt now on. 39108: >","title":"Add Console and Shell to Blinky"},{"location":"os/tutorials/blinky_console/#enabling-the-console-and-shell-for-blinky","text":"This tutorial shows you how to add the Console and Shell to the Blinky application and interact with it over a serial line connection.","title":"Enabling The Console and Shell for Blinky"},{"location":"os/tutorials/blinky_console/#prerequisites","text":"Work through one of the Blinky Tutorials to create and build a Blinky application for one of the boards. Have a serial setup .","title":"Prerequisites"},{"location":"os/tutorials/blinky_console/#use-an-existing-project","text":"Since all we're doing is adding the shell and console capability to blinky, we assume that you have worked through at least some of the other tutorials, and have an existing project. For this example, we'll be modifying the blinky on nrf52 project to enable the shell and console connectivity. You can use blinky on a different board.","title":"Use an Existing Project"},{"location":"os/tutorials/blinky_console/#modify-the-dependencies-and-configuration","text":"Add the following dependencies to your application target's pkg.yml file: pkg.deps: - \"@apache-mynewt-core/sys/console/full\" - \"@apache-mynewt-core/sys/shell\" - \"@apache-mynewt-core/sys/sysinit\" This lets the newt system know that it needs to pull in the code for the console and the shell. Modify the system configuration settings to enable Shell and Console ticks and prompt. Add the following to your application target's syscfg.yml file: syscfg.vals: # Enable the shell task. SHELL_TASK: 1 # Enable Console OS Ticks CONSOLE_TICKS: 1 # Enable Console Prompt CONSOLE_PROMPT: 1","title":"Modify the Dependencies and Configuration"},{"location":"os/tutorials/blinky_console/#use-the-os-default-event-queue-to-process-blinky-timer-and-shell-events","text":"Mynewt creates a main task that executes the application main() function. It also creates an OS default event queue that packages can use to queue their events. Shell uses the OS default event queue for Shell events, and main() can process the events in the context of the main task. Blinky's main.c is very simple. It only has a main() function that executes an infinite loop to toggle the LED and sleep for one second. We will modify blinky: To use os_callout to generate a timer event every one second instead of sleeping. The timer events are added to the OS default event queue. To process events from the OS default event queue inside the infinite loop in main() . This allows the main task to process both Shell events and the timer events to toggle the LED from the OS default event queue.","title":"Use the OS Default Event Queue to Process Blinky Timer and Shell Events"},{"location":"os/tutorials/blinky_console/#modify-mainc","text":"Initialize a os_callout timer and move the toggle code from the while loop in main() to the event callback function. Add the following code above the main() function: /* The timer callout */ static struct os_callout blinky_callout ; /* * Event callback function for timer events. It toggles the led pin. */ static void timer_ev_cb ( struct os_event *ev ) { assert ( ev != NULL ); ++g_task1_loops ; hal_gpio_toggle ( g_led_pin ); os_callout_reset ( &blinky_callout , OS_TICKS_PER_SEC ); } static void init_timer ( void ) { /* * Initialize the callout for a timer event. */ os_callout_init ( &blinky_callout , os_eventq_dflt_get (), timer_ev_cb , NULL ); os_callout_reset ( &blinky_callout , OS_TICKS_PER_SEC ); } In main() , add the call to the init_timer() function before the while loop and modify the while loop to process events from the OS default event queue: main ( int argc , char **argv ) { int rc ; #ifdef ARCH_sim mcu_sim_parse_args ( argc , argv ); #endif sysinit (); g_led_pin = LED_BLINK_PIN ; hal_gpio_init_out ( g_led_pin , 1 ); init_timer (); while ( 1 ) { os_eventq_run ( os_eventq_dflt_get ()); } assert ( 0 ) return rc ; }","title":"Modify main.c"},{"location":"os/tutorials/blinky_console/#build-the-blinky-application-target","text":"We're not going to build the bootloader here since we are assuming that you have already built and loaded it during previous tutorials. Run the newt build nrf52_blinky command to build the Blinky application: $ newt build nrf52_blinky ... Archiving util_mem.a Linking ~/dev/myproj/bin/targets/nrf52_blinky/app/apps/blinky/blinky.elf Target successfully built: targets/nrf52_blinky","title":"Build the Blinky Application Target"},{"location":"os/tutorials/blinky_console/#sign-and-create-the-blinky-application-image","text":"Run the newt create-image nrf52_blinky 1.0.0 command to create and sign the application image. You may assign an arbitrary version (e.g. 1.0.0) to the image. $ newt create-image nrf52_blinky 1.0.0 App image succesfully generated: ~/dev/myproj/bin/targets/nrf52_blinky/app/apps/blinky/blinky.img","title":"Sign and Create the Blinky Application Image"},{"location":"os/tutorials/blinky_console/#load-the-image","text":"Make sure the USB connector is in place and the power LED on the board is lit. Use the Power ON/OFF switch to reset the board after loading the image. Run the newt load nrf52_blinky command to load the Blinky application image onto the board. $ newt load nrf52_blinky Loading app image into slot 1","title":"Load the Image"},{"location":"os/tutorials/blinky_console/#set-up-a-serial-connection","text":"You'll need a Serial connection to see the output of your program. You can reference the Serial Port Setup Tutorial for more information on setting up your serial communication.","title":"Set Up a Serial Connection"},{"location":"os/tutorials/blinky_console/#communicate-with-the-application","text":"Once you have a connection set up, you can connect to your device as follows: On Mac OS and Linux platforms, you can run minicom -D /dev/tty.usbserial-<port> -b 115200 to connect to the console of your app. Note that on Linux, the format of the port name is /dev/ttyUSB<N> , where N is a number. On Windows, you can use a terminal application such as PuTTY to connect to the device. If you located your port from a MinGW terminal, the port name format is /dev/ttyS<N> , where N is a number. You must map the port name to a Windows COM port: /dev/ttyS<N> maps to COM<N+1> . For example, /dev/ttyS2 maps to COM3 . You can also use the Windows Device Manager to locate the COM port. To test and make sure that the Shell is running, first just hit : 3534: > You can try some commands: 3609: > ? Commands: 8841: echo ? prompt ticks tasks mempools 8843: date b 8844: > ticks off Console Ticks off > prompt off Prompt now off. ticks on 33383: Console Ticks on 33568: prompt on 39108: Prompt now on. 39108: >","title":"Communicate with the Application"},{"location":"os/tutorials/blinky_primo/","text":"Blinky, your \"Hello World!\", on Arduino Primo This tutorial shows you how to create, build, and run the Blinky application on an Arduino Primo board. Note that the Mynewt OS will run on the nRF52 chip in the Arduino Primo board. However, the board support package for the Arduino Primo is different from the nRF52 dev kit board support package. Prerequisites Meet the the prerequisites listed in Project Blinky . Have an Arduino Primo board. Install a debugger. Choose one of the two options below: Option 1 requires additional hardware but very easy to set up. Option 1 Segger J-Link Debug Probe - any model (this tutorial has been tested with J-Link EDU and J-Link Pro) J-Link 9 pin Cortex-M Adapter that allows JTAG, SWD and SWO connections between J-Link and Cortex M based target hardware systems Install the Segger JLINK Software and documentation pack . Option 2 This board requires a patch version of OpenOCD 0.10.0 that is in development. See Install OpenOCD instructions to install it if you do not have this version installed. You can now use openocd to upload to Arduino Primo board via the USB port itself. Create a Project Create a new project if you do not have an existing one. You can skip this step and proceed to create the targets if you already created a project. Run the following commands to create a new project: $ mkdir ~/dev $ cd ~/dev $ newt new myproj Downloading project skeleton from apache/incubator-mynewt-blinky... Installing skeleton in myproj... Project myproj successfully created. $ cd myproj $ newt install apache-mynewt-core $ Create the Targets Create two targets for the Arduino Primo board - one for the bootloader and one for the Blinky application. Run the following newt target commands, from your project directory, to create a bootloader target. We name the target primo_boot . $ newt target create primo_boot $ newt target set primo_boot app=@apache-mynewt-core/apps/boot bsp=@apache-mynewt-core/hw/bsp/arduino_primo_nrf52 build_profile=optimized Run the following newt target commands to create a target for the Blinky application. We name the target primoblinky . $ newt target create primoblinky $ newt target set primoblinky app=apps/blinky bsp=@apache-mynewt-core/hw/bsp/arduino_primo_nrf52 build_profile=debug If you are using openocd, run the following newt target set commands: $ newt target set primoblinky syscfg=OPENOCD_DEBUG=1 $ newt target set primo_boot syscfg=OPENOCD_DEBUG=1 You can run the newt target show command to verify the target settings: $ newt target show targets/my_blinky_sim app=apps/blinky bsp=@apache-mynewt-core/hw/bsp/native build_profile=debug targets/primo_boot app=@apache-mynewt-core/apps/boot bsp=@apache-mynewt-core/hw/bsp/arduino_primo_nrf52 build_profile=optimized targets/primoblinky app=@apache-mynewt-core/apps/blinky bsp=@apache-mynewt-core/hw/bsp/arduino_primo_nrf52 build_profile=optimized Build the Target Executables Run the newt build primo_boot command to build the bootloader: $ newt build primo_boot Building target targets/primo_boot Compiling repos/apache-mynewt-core/boot/bootutil/src/image_rsa.c Compiling repos/apache-mynewt-core/boot/bootutil/src/image_ec256.c Compiling repos/apache-mynewt-core/crypto/mbedtls/src/aes.c Compiling repos/apache-mynewt-core/apps/boot/src/boot.c Compiling repos/apache-mynewt-core/boot/bootutil/src/image_ec.c Compiling repos/apache-mynewt-core/boot/bootutil/src/loader.c Compiling repos/apache-mynewt-core/boot/bootutil/src/bootutil_misc.c ... Archiving sys_mfg.a Archiving sys_sysinit.a Archiving util_mem.a Linking ~/dev/myproj/bin/targets/primo_boot/app/apps/boot/boot.elf Target successfully built: targets/primo_boot Run the newt build primoblinky command to build the Blinky application: $ newt build primoblinky Building target targets/primoblinky Compiling repos/apache-mynewt-core/hw/drivers/uart/src/uart.c Assembling repos/apache-mynewt-core/hw/bsp/arduino_primo_nrf52/src/arch/cortex_m4/gcc_startup_nrf52.s Compiling repos/apache-mynewt-core/hw/bsp/arduino_primo_nrf52/src/sbrk.c Compiling repos/apache-mynewt-core/hw/cmsis-core/src/cmsis_nvic.c Assembling repos/apache-mynewt-core/hw/bsp/arduino_primo_nrf52/src/arch/cortex_m4/gcc_startup_nrf52_split.s Compiling apps/blinky/src/main.c Compiling repos/apache-mynewt-core/hw/drivers/uart/uart_bitbang/src/uart_bitbang.c Compiling repos/apache-mynewt-core/hw/bsp/arduino_primo_nrf52/src/hal_bsp.c Archiving sys_mfg.a Archiving sys_sysinit.a Archiving util_mem.a Linking ~/dev/myproj/bin/targets/primoblinky/app/apps/blinky/blinky.elf Target successfully built: targets/primoblinky Sign and Create the Blinky Application Image Run the newt create-image primoblinky 1.0.0 command to create and sign the application image. You may assign an arbitrary version (e.g. 1.0.0) to the image. $ newt create-image primoblinky 1.0.0 App image succesfully generated: ~/dev/myproj/bin/targets/primoblinky/app/apps/blinky/blinky.img Connect to the Board Connect a micro USB cable to the Arduino Primo board and to your computer's USB port. If you are using the Segger J-Link debug probe, connect the debug probe to the JTAG port on the Primo board using the Jlink 9-pin adapter and cable. Note that there are two JTAG ports on the board. Use the one nearest to the reset button as shown in the picture. Note: If you are using the OpenOCD debugger, you do not need to attach this connector. Load the Bootloader Run the newt load primo_boot command to load the bootloader onto the board: $ newt load primo_boot Loading bootloader $ Note: If you are using OpenOCD on a Windows platform and you get an unable to find CMSIS-DAP device error, you will need to download and install the mbed Windows serial port driver from https://developer.mbed.org/handbook/Windows-serial-configuration . Follow the instructions from the site to install the driver. Here are some additional notes about the installation: The instructions indicate that the mbed Windows serial port driver is not required for Windows 10. If you are using Windows 10 and get the unable to find CMSIS-DAP device error, we recommend that you install the driver. If the driver installation fails, we recommend that you download and install the Arduino Primo CMSIS-DAP driver. Perform the following steps: Download the Arduino Primo CMSIS-DAP driver and extract the zip file. Start Device Manager. Select Other Devices > CMSIS-DAP CDC > Properties > Drivers > Update Driver... . Select Browse my computer for driver software . Select the Arduino Driver folder where extracted the drivers to (check the include subfolders). Click Next to install the driver. Run the newt load primo_boot command again. Load the Blinky Application Image Run the newt load primoblinky command to load the Blinky application image onto the board. $ newt load primoblinky Loading app image into slot 1 $ You should see the orange LED (L13), below the ON LED, on the board blink! Note: If the LED does not blink, try resetting the board. Erase Flash If you want to erase the flash and load the image again, use JLinkExe and issue the erase command when you are using the Jlink debug probe: Note: On Windows: Run the jlink command with the same arguments from a Windows Command Prompt terminal. $ JLinkExe -device nRF52 -speed 4000 -if SWD SEGGER J-Link Commander V5.12c (Compiled Apr 21 2016 16:05:51) DLL version V5.12c, compiled Apr 21 2016 16:05:45 Connecting to J-Link via USB...O.K. Firmware: J-Link OB-SAM3U128-V2-NordicSemi compiled Mar 15 2016 18:03:17 Hardware version: V1.00 S/N: 682863966 VTref = 3.300V Type \"connect\" to establish a target connection, '?' for help J-Link>erase Cortex-M4 identified. Erasing device (0;?i?)... Comparing flash [100%] Done. Erasing flash [100%] Done. Verifying flash [100%] Done. J-Link: Flash download: Total time needed: 0.363s (Prepare: 0.093s, Compare: 0.000s, Erase: 0.262s, Program: 0.000s, Verify: 0.000s, Restore: 0.008s) Erasing done. J-Link>exit $ If you are using the OpenOCD debugger, run the newt debug primoblinky command and issue the highlighted command at the (gdb) prompt: Note: The output of the debug session below is for Mac OS and Linux platforms. On Windows, openocd and gdb are started in separate Windows Command Prompt terminals, and the terminals are automatically closed when you quit gdb. In addition, the output of openocd is logged to the openocd.log file in your project's base directory instead of the terminal. $newt debug primoblinky [~/dev/myproj/repos/apache-mynewt-core/hw/bsp/arduino_primo_nrf52/primo_debug.sh ~/dev/myproj/repos/apache-mynewt-core/hw/bsp/arduino_primo_nrf52 ~/dev/myproj/bin/targets/primoblinky/app/apps/blinky/blinky] Open On-Chip Debugger 0.10.0-dev-snapshot (2017-03-28-11:24) ... os_tick_idle (ticks=128) at repos/apache-mynewt-core/hw/mcu/nordic/nrf52xxx/src/hal_os_tick.c:200 warning: Source file is more recent than executable. 200 if (ticks > 0) { (gdb) mon nrf52 mass_erase","title":"Blinky on Arduino Primo"},{"location":"os/tutorials/blinky_primo/#blinky-your-hello-world-on-arduino-primo","text":"This tutorial shows you how to create, build, and run the Blinky application on an Arduino Primo board. Note that the Mynewt OS will run on the nRF52 chip in the Arduino Primo board. However, the board support package for the Arduino Primo is different from the nRF52 dev kit board support package.","title":"Blinky, your \"Hello World!\", on Arduino Primo"},{"location":"os/tutorials/blinky_primo/#prerequisites","text":"Meet the the prerequisites listed in Project Blinky . Have an Arduino Primo board. Install a debugger. Choose one of the two options below: Option 1 requires additional hardware but very easy to set up.","title":"Prerequisites"},{"location":"os/tutorials/blinky_primo/#option-1","text":"Segger J-Link Debug Probe - any model (this tutorial has been tested with J-Link EDU and J-Link Pro) J-Link 9 pin Cortex-M Adapter that allows JTAG, SWD and SWO connections between J-Link and Cortex M based target hardware systems Install the Segger JLINK Software and documentation pack .","title":"Option 1"},{"location":"os/tutorials/blinky_primo/#option-2","text":"This board requires a patch version of OpenOCD 0.10.0 that is in development. See Install OpenOCD instructions to install it if you do not have this version installed. You can now use openocd to upload to Arduino Primo board via the USB port itself.","title":"Option 2"},{"location":"os/tutorials/blinky_primo/#create-a-project","text":"Create a new project if you do not have an existing one. You can skip this step and proceed to create the targets if you already created a project. Run the following commands to create a new project: $ mkdir ~/dev $ cd ~/dev $ newt new myproj Downloading project skeleton from apache/incubator-mynewt-blinky... Installing skeleton in myproj... Project myproj successfully created. $ cd myproj $ newt install apache-mynewt-core $","title":"Create a Project"},{"location":"os/tutorials/blinky_primo/#create-the-targets","text":"Create two targets for the Arduino Primo board - one for the bootloader and one for the Blinky application. Run the following newt target commands, from your project directory, to create a bootloader target. We name the target primo_boot . $ newt target create primo_boot $ newt target set primo_boot app=@apache-mynewt-core/apps/boot bsp=@apache-mynewt-core/hw/bsp/arduino_primo_nrf52 build_profile=optimized Run the following newt target commands to create a target for the Blinky application. We name the target primoblinky . $ newt target create primoblinky $ newt target set primoblinky app=apps/blinky bsp=@apache-mynewt-core/hw/bsp/arduino_primo_nrf52 build_profile=debug If you are using openocd, run the following newt target set commands: $ newt target set primoblinky syscfg=OPENOCD_DEBUG=1 $ newt target set primo_boot syscfg=OPENOCD_DEBUG=1 You can run the newt target show command to verify the target settings: $ newt target show targets/my_blinky_sim app=apps/blinky bsp=@apache-mynewt-core/hw/bsp/native build_profile=debug targets/primo_boot app=@apache-mynewt-core/apps/boot bsp=@apache-mynewt-core/hw/bsp/arduino_primo_nrf52 build_profile=optimized targets/primoblinky app=@apache-mynewt-core/apps/blinky bsp=@apache-mynewt-core/hw/bsp/arduino_primo_nrf52 build_profile=optimized","title":"Create the Targets"},{"location":"os/tutorials/blinky_primo/#build-the-target-executables","text":"Run the newt build primo_boot command to build the bootloader: $ newt build primo_boot Building target targets/primo_boot Compiling repos/apache-mynewt-core/boot/bootutil/src/image_rsa.c Compiling repos/apache-mynewt-core/boot/bootutil/src/image_ec256.c Compiling repos/apache-mynewt-core/crypto/mbedtls/src/aes.c Compiling repos/apache-mynewt-core/apps/boot/src/boot.c Compiling repos/apache-mynewt-core/boot/bootutil/src/image_ec.c Compiling repos/apache-mynewt-core/boot/bootutil/src/loader.c Compiling repos/apache-mynewt-core/boot/bootutil/src/bootutil_misc.c ... Archiving sys_mfg.a Archiving sys_sysinit.a Archiving util_mem.a Linking ~/dev/myproj/bin/targets/primo_boot/app/apps/boot/boot.elf Target successfully built: targets/primo_boot Run the newt build primoblinky command to build the Blinky application: $ newt build primoblinky Building target targets/primoblinky Compiling repos/apache-mynewt-core/hw/drivers/uart/src/uart.c Assembling repos/apache-mynewt-core/hw/bsp/arduino_primo_nrf52/src/arch/cortex_m4/gcc_startup_nrf52.s Compiling repos/apache-mynewt-core/hw/bsp/arduino_primo_nrf52/src/sbrk.c Compiling repos/apache-mynewt-core/hw/cmsis-core/src/cmsis_nvic.c Assembling repos/apache-mynewt-core/hw/bsp/arduino_primo_nrf52/src/arch/cortex_m4/gcc_startup_nrf52_split.s Compiling apps/blinky/src/main.c Compiling repos/apache-mynewt-core/hw/drivers/uart/uart_bitbang/src/uart_bitbang.c Compiling repos/apache-mynewt-core/hw/bsp/arduino_primo_nrf52/src/hal_bsp.c Archiving sys_mfg.a Archiving sys_sysinit.a Archiving util_mem.a Linking ~/dev/myproj/bin/targets/primoblinky/app/apps/blinky/blinky.elf Target successfully built: targets/primoblinky","title":"Build the Target Executables"},{"location":"os/tutorials/blinky_primo/#sign-and-create-the-blinky-application-image","text":"Run the newt create-image primoblinky 1.0.0 command to create and sign the application image. You may assign an arbitrary version (e.g. 1.0.0) to the image. $ newt create-image primoblinky 1.0.0 App image succesfully generated: ~/dev/myproj/bin/targets/primoblinky/app/apps/blinky/blinky.img","title":"Sign and Create the Blinky Application Image"},{"location":"os/tutorials/blinky_primo/#connect-to-the-board","text":"Connect a micro USB cable to the Arduino Primo board and to your computer's USB port. If you are using the Segger J-Link debug probe, connect the debug probe to the JTAG port on the Primo board using the Jlink 9-pin adapter and cable. Note that there are two JTAG ports on the board. Use the one nearest to the reset button as shown in the picture. Note: If you are using the OpenOCD debugger, you do not need to attach this connector.","title":"Connect to the Board"},{"location":"os/tutorials/blinky_primo/#load-the-bootloader","text":"Run the newt load primo_boot command to load the bootloader onto the board: $ newt load primo_boot Loading bootloader $ Note: If you are using OpenOCD on a Windows platform and you get an unable to find CMSIS-DAP device error, you will need to download and install the mbed Windows serial port driver from https://developer.mbed.org/handbook/Windows-serial-configuration . Follow the instructions from the site to install the driver. Here are some additional notes about the installation: The instructions indicate that the mbed Windows serial port driver is not required for Windows 10. If you are using Windows 10 and get the unable to find CMSIS-DAP device error, we recommend that you install the driver. If the driver installation fails, we recommend that you download and install the Arduino Primo CMSIS-DAP driver. Perform the following steps: Download the Arduino Primo CMSIS-DAP driver and extract the zip file. Start Device Manager. Select Other Devices > CMSIS-DAP CDC > Properties > Drivers > Update Driver... . Select Browse my computer for driver software . Select the Arduino Driver folder where extracted the drivers to (check the include subfolders). Click Next to install the driver. Run the newt load primo_boot command again.","title":"Load the Bootloader"},{"location":"os/tutorials/blinky_primo/#load-the-blinky-application-image","text":"Run the newt load primoblinky command to load the Blinky application image onto the board. $ newt load primoblinky Loading app image into slot 1 $ You should see the orange LED (L13), below the ON LED, on the board blink! Note: If the LED does not blink, try resetting the board.","title":"Load the Blinky Application Image"},{"location":"os/tutorials/blinky_primo/#erase-flash","text":"If you want to erase the flash and load the image again, use JLinkExe and issue the erase command when you are using the Jlink debug probe: Note: On Windows: Run the jlink command with the same arguments from a Windows Command Prompt terminal. $ JLinkExe -device nRF52 -speed 4000 -if SWD SEGGER J-Link Commander V5.12c (Compiled Apr 21 2016 16:05:51) DLL version V5.12c, compiled Apr 21 2016 16:05:45 Connecting to J-Link via USB...O.K. Firmware: J-Link OB-SAM3U128-V2-NordicSemi compiled Mar 15 2016 18:03:17 Hardware version: V1.00 S/N: 682863966 VTref = 3.300V Type \"connect\" to establish a target connection, '?' for help J-Link>erase Cortex-M4 identified. Erasing device (0;?i?)... Comparing flash [100%] Done. Erasing flash [100%] Done. Verifying flash [100%] Done. J-Link: Flash download: Total time needed: 0.363s (Prepare: 0.093s, Compare: 0.000s, Erase: 0.262s, Program: 0.000s, Verify: 0.000s, Restore: 0.008s) Erasing done. J-Link>exit $ If you are using the OpenOCD debugger, run the newt debug primoblinky command and issue the highlighted command at the (gdb) prompt: Note: The output of the debug session below is for Mac OS and Linux platforms. On Windows, openocd and gdb are started in separate Windows Command Prompt terminals, and the terminals are automatically closed when you quit gdb. In addition, the output of openocd is logged to the openocd.log file in your project's base directory instead of the terminal. $newt debug primoblinky [~/dev/myproj/repos/apache-mynewt-core/hw/bsp/arduino_primo_nrf52/primo_debug.sh ~/dev/myproj/repos/apache-mynewt-core/hw/bsp/arduino_primo_nrf52 ~/dev/myproj/bin/targets/primoblinky/app/apps/blinky/blinky] Open On-Chip Debugger 0.10.0-dev-snapshot (2017-03-28-11:24) ... os_tick_idle (ticks=128) at repos/apache-mynewt-core/hw/mcu/nordic/nrf52xxx/src/hal_os_tick.c:200 warning: Source file is more recent than executable. 200 if (ticks > 0) { (gdb) mon nrf52 mass_erase","title":"Erase Flash"},{"location":"os/tutorials/blinky_sram_olimex/","text":"Run Blinky from SRAM without bootloader Objective To download an application image directly into the embedded SRAM in the microcontroller and run it without the bootloader. This tutorial describes how you do it on an Olimex STM32 board. What you need STM32-E407 development board from Olimex. You can order it from http://www.mouser.com , http://www.digikey.com , and other places. ARM-USB-TINY-H connector with JTAG interface for debugging ARM microcontrollers (comes with the ribbon cable to hook up to the board) USB A-B type cable to connect the debugger to your personal computer Personal Computer with Mac OS (Mac: OS X Yosemite Version 10.10.5) or Linux box (Ubuntu 14.10: Utopic Unicorn) An account on Github repository and git installed on your computer. It is assumed you have already installed newt tool. It is assumed you already installed native tools as described here Also, we assume that you're familiar with UNIX shells. Let's gets started! Prepare the Software Make sure the PATH environment variable includes the $HOME/dev/go/bin directory. Create a project Create a new project to hold your work. For a deeper understanding, you can read about project creation in Get Started -- Creating Your First Project or just follow the commands below. $ mkdir ~/dev $ cd ~/dev $ newt new myproj Downloading project skeleton from apache/incubator-mynewt-blinky... Installing skeleton in myproj... Project myproj successfully created. $cd myproj $ newt install -v apache-mynewt-core Downloading repository description for apache-mynewt-core... success! ... apache-mynewt-core successfully installed version 0.7.9-none Create a target Change directory to ~/dev/myproj directory and define the blinky target inside myproj, using the newt tool. Starting with the target name, assign specific aspects of the project, as shown below, to pull the appropriate packages and build the right bundle or list for the board. For example, we set the build_profile, board support package (bsp), and app. $ newt target create blinky $ newt target set blinky build_profile=debug $ newt target set blinky bsp=@apache-mynewt-core/hw/bsp/olimex_stm32-e407_devboard $ newt target set blinky app=apps/blinky $ newt target show blinky targets/blinky app=apps/blinky bsp=hw/bsp/olimex_stm32-e407_devboard build_profile=debug Build the image Next, let's build the image for the above target. By default, the linker script within the hw/bsp/olimex_stm32-e407_devboard package builds an image for flash memory, which we don't want; instead, we want an image for the SRAM, so you need to switch that script with run_from_sram.ld . Afer you build the target, you can find the executable blinky.elf in the project directory ~/dev/myproj/bin/blinky/apps/blinky/. $ cd ~/dev/myproj/repos/apache-mynewt-core/hw/bsp/olimex_stm32-e407_devboard/ $ diff olimex_stm32-e407_devboard.ld run_from_sram.ld (some diff will be displayed) $ cp run_from_sram.ld olimex_stm32-e407_devboard.ld $ cd ~/dev/myproj $ newt build blinky Compiling case.c Compiling suite.c ... Linking blinky.elf App successfully built:~/dev/myproj/bin/blinky/apps/blinky/blinky.elf $ ls ~/dev/myproj/bin/blinky/apps/blinky/ blinky.elf blinky.elf.bin blinky.elf.cmd blinky.elf.lst blinky.elf.map Prepare the hardware to boot from embedded SRAM Locate the boot jumpers on the board. B1_1/B1_0 and B0_1/B0_0 are PTH jumpers. Note that because the markings on the board may not always be accurate, when in doubt, you should always refer to the manual for the correct positioning. Since the jumpers are a pair, they should move together, and as such, the pair is responsible for the boot mode when bootloader is present. To locate the bootloader, the board searches in three places: User Flash Memory, System Memory or the Embedded SRAM. For this Blinky project, we will configure it to boot from SRAM by jumpering B0_1 and B1_1 . Connect USB-OTG#2 in the picture above to a USB port on your computer (or a powered USB hub to make sure there is enough power available to the board). The red PWR LED should be lit. Connect the JTAG connector to the SWD/JTAG interface on the board. The other end of the cable should be connected to the USB port or hub of your computer. Let's Go! Ensure that you are in the blinky project directory with the blinky.elf executable. Run the debug command in the newt tool. You'll see some status messages as shown below. In case you need to halt the debugging session, you can issue an -c \"reset halt\" command. $ newt debug blinky Debugging with ~/dev/core/hw/bsp/olimex_... Debugging ~/dev/core/project/blinky/bin/blinky/blinky.elf GNU gdb (GNU Tools for ARM Embedded Processors) 7.8.0.20150604-cvs Copyright (C) 2014 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 <http://gnu.org/licenses/gpl.html> ... (info) ... target state: halted target halted due to debug-request, current mode: Thread xPSR: 0x01000000 pc: 0x080003c0 msp: 0x10010000 Info : accepting 'gdb' connection on tcp/3333 Info : device id = 0x10036413 Info : flash size = 1024kbytes Check the value of the msp (main service pointer) register. If it is not 0x10010000 as indicated above, you will have to manually set it after you open the gdb tool and load the image on it. For example, (gdb) set $msp=0x10010000 Now load the image and type \"c\" or \"continue\" from the GNU debugger. (gdb) load ~/dev/myproj/bin/blinky/apps/blinky/blinky.elf Loading section .text, size 0x16b88 lma 0x20000000 Loading section .ARM.exidx, size 0x18 lma 0x20016b88 Loading section .data, size 0x9ec lma 0x20016ba0 Start address 0x200004b8, load size 95628 Transfer rate: 74 KB/sec, 3825 bytes/write. (gdb) c Continuing. Voil\u00e0! The board's LED should be blinking at 1 Hz. Success!","title":"Blinky sram olimex"},{"location":"os/tutorials/blinky_sram_olimex/#run-blinky-from-sram-without-bootloader","text":"","title":"Run Blinky from SRAM without bootloader"},{"location":"os/tutorials/blinky_sram_olimex/#objective","text":"To download an application image directly into the embedded SRAM in the microcontroller and run it without the bootloader. This tutorial describes how you do it on an Olimex STM32 board.","title":"Objective"},{"location":"os/tutorials/blinky_sram_olimex/#what-you-need","text":"STM32-E407 development board from Olimex. You can order it from http://www.mouser.com , http://www.digikey.com , and other places. ARM-USB-TINY-H connector with JTAG interface for debugging ARM microcontrollers (comes with the ribbon cable to hook up to the board) USB A-B type cable to connect the debugger to your personal computer Personal Computer with Mac OS (Mac: OS X Yosemite Version 10.10.5) or Linux box (Ubuntu 14.10: Utopic Unicorn) An account on Github repository and git installed on your computer. It is assumed you have already installed newt tool. It is assumed you already installed native tools as described here Also, we assume that you're familiar with UNIX shells. Let's gets started!","title":"What you need"},{"location":"os/tutorials/blinky_sram_olimex/#prepare-the-software","text":"Make sure the PATH environment variable includes the $HOME/dev/go/bin directory.","title":"Prepare the Software"},{"location":"os/tutorials/blinky_sram_olimex/#create-a-project","text":"Create a new project to hold your work. For a deeper understanding, you can read about project creation in Get Started -- Creating Your First Project or just follow the commands below. $ mkdir ~/dev $ cd ~/dev $ newt new myproj Downloading project skeleton from apache/incubator-mynewt-blinky... Installing skeleton in myproj... Project myproj successfully created. $cd myproj $ newt install -v apache-mynewt-core Downloading repository description for apache-mynewt-core... success! ... apache-mynewt-core successfully installed version 0.7.9-none","title":"Create a project"},{"location":"os/tutorials/blinky_sram_olimex/#create-a-target","text":"Change directory to ~/dev/myproj directory and define the blinky target inside myproj, using the newt tool. Starting with the target name, assign specific aspects of the project, as shown below, to pull the appropriate packages and build the right bundle or list for the board. For example, we set the build_profile, board support package (bsp), and app. $ newt target create blinky $ newt target set blinky build_profile=debug $ newt target set blinky bsp=@apache-mynewt-core/hw/bsp/olimex_stm32-e407_devboard $ newt target set blinky app=apps/blinky $ newt target show blinky targets/blinky app=apps/blinky bsp=hw/bsp/olimex_stm32-e407_devboard build_profile=debug","title":"Create a target"},{"location":"os/tutorials/blinky_sram_olimex/#build-the-image","text":"Next, let's build the image for the above target. By default, the linker script within the hw/bsp/olimex_stm32-e407_devboard package builds an image for flash memory, which we don't want; instead, we want an image for the SRAM, so you need to switch that script with run_from_sram.ld . Afer you build the target, you can find the executable blinky.elf in the project directory ~/dev/myproj/bin/blinky/apps/blinky/. $ cd ~/dev/myproj/repos/apache-mynewt-core/hw/bsp/olimex_stm32-e407_devboard/ $ diff olimex_stm32-e407_devboard.ld run_from_sram.ld (some diff will be displayed) $ cp run_from_sram.ld olimex_stm32-e407_devboard.ld $ cd ~/dev/myproj $ newt build blinky Compiling case.c Compiling suite.c ... Linking blinky.elf App successfully built:~/dev/myproj/bin/blinky/apps/blinky/blinky.elf $ ls ~/dev/myproj/bin/blinky/apps/blinky/ blinky.elf blinky.elf.bin blinky.elf.cmd blinky.elf.lst blinky.elf.map","title":"Build the image"},{"location":"os/tutorials/blinky_sram_olimex/#prepare-the-hardware-to-boot-from-embedded-sram","text":"Locate the boot jumpers on the board. B1_1/B1_0 and B0_1/B0_0 are PTH jumpers. Note that because the markings on the board may not always be accurate, when in doubt, you should always refer to the manual for the correct positioning. Since the jumpers are a pair, they should move together, and as such, the pair is responsible for the boot mode when bootloader is present. To locate the bootloader, the board searches in three places: User Flash Memory, System Memory or the Embedded SRAM. For this Blinky project, we will configure it to boot from SRAM by jumpering B0_1 and B1_1 . Connect USB-OTG#2 in the picture above to a USB port on your computer (or a powered USB hub to make sure there is enough power available to the board). The red PWR LED should be lit. Connect the JTAG connector to the SWD/JTAG interface on the board. The other end of the cable should be connected to the USB port or hub of your computer.","title":"Prepare the hardware to boot from embedded SRAM"},{"location":"os/tutorials/blinky_sram_olimex/#lets-go","text":"Ensure that you are in the blinky project directory with the blinky.elf executable. Run the debug command in the newt tool. You'll see some status messages as shown below. In case you need to halt the debugging session, you can issue an -c \"reset halt\" command. $ newt debug blinky Debugging with ~/dev/core/hw/bsp/olimex_... Debugging ~/dev/core/project/blinky/bin/blinky/blinky.elf GNU gdb (GNU Tools for ARM Embedded Processors) 7.8.0.20150604-cvs Copyright (C) 2014 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 <http://gnu.org/licenses/gpl.html> ... (info) ... target state: halted target halted due to debug-request, current mode: Thread xPSR: 0x01000000 pc: 0x080003c0 msp: 0x10010000 Info : accepting 'gdb' connection on tcp/3333 Info : device id = 0x10036413 Info : flash size = 1024kbytes Check the value of the msp (main service pointer) register. If it is not 0x10010000 as indicated above, you will have to manually set it after you open the gdb tool and load the image on it. For example, (gdb) set $msp=0x10010000 Now load the image and type \"c\" or \"continue\" from the GNU debugger. (gdb) load ~/dev/myproj/bin/blinky/apps/blinky/blinky.elf Loading section .text, size 0x16b88 lma 0x20000000 Loading section .ARM.exidx, size 0x18 lma 0x20016b88 Loading section .data, size 0x9ec lma 0x20016ba0 Start address 0x200004b8, load size 95628 Transfer rate: 74 KB/sec, 3825 bytes/write. (gdb) c Continuing. Voil\u00e0! The board's LED should be blinking at 1 Hz. Success!","title":"Let's Go!"},{"location":"os/tutorials/blinky_stm32f4disc/","text":"Blinky, your \"Hello World!\", on STM32F4-Discovery This tutorial shows you how to create, build, and run the Blinky application on the STM32F4-Discovery board. Prerequisites Meet the prerequisites listed in Project Blinky . Have a STM32F4-Discovery board. Have a USB type A to Mini-B cable. Install a patched version of OpenOCD 0.10.0 described in Install OpenOCD . Create a Project Create a new project if you do not have an existing one. You can skip this step and proceed to create the targets if you already have a project created. Run the following commands to create a new project: $ mkdir ~/dev $ cd ~/dev $ newt new myproj Downloading project skeleton from apache/incubator-mynewt-blinky... Installing skeleton in myproj... Project myproj successfully created. $ cd myproj $ newt install apache-mynewt-core $ Create the Targets Create two targets for the STM32F4-Discovery board - one for the bootloader and one for the Blinky application. Run the following newt target commands, from your project directory, to create a bootloader target. We name the target stm32f4disc_boot : $ newt target create stm32f4disc_boot $ newt target set stm32f4disc_boot app=@apache-mynewt-core/apps/boot $ newt target set stm32f4disc_boot bsp=@apache-mynewt-core/hw/bsp/stm32f4discovery $ newt target set stm32f4disc_boot build_profile=optimized Run the following newt target commands to create a target for the Blinky application. We name the target stm32f4disc_blinky : $ newt target create stm32f4disc_blinky $ newt target set stm32f4disc_blinky app=apps/blinky $ newt target set stm32f4disc_blinky bsp=@apache-mynewt-core/hw/bsp/stm32f4discovery $ newt target set stm32f4disc_blinky build_profile=debug You can run the newt target show command to verify the target settings: $ newt target show targets/my_blinky_sim app=apps/blinky bsp=@apache-mynewt-core/hw/bsp/native build_profile=debug targets/stm32f4disc_blinky app=apps/blinky bsp=@apache-mynewt-core/hw/bsp/stm32f4discovery build_profile=debug targets/stm32f4disc_boot app=@apache-mynewt-core/apps/boot bsp=@apache-mynewt-core/hw/bsp/stm32f4discovery build_profile=optimized Build the Target Executables Run the newt build stm32f4disc_boot command to build the bootloader: $ newt build stm32f4disc_boot Building target targets/stm32f4disc_boot Compiling repos/apache-mynewt-core/boot/bootutil/src/image_ec.c Compiling repos/apache-mynewt-core/boot/bootutil/src/image_ec256.c Compiling repos/apache-mynewt-core/boot/bootutil/src/bootutil_misc.c Compiling repos/apache-mynewt-core/apps/boot/src/boot.c Compiling repos/apache-mynewt-core/boot/bootutil/src/image_rsa.c Compiling repos/apache-mynewt-core/boot/bootutil/src/image_validate.c Compiling repos/apache-mynewt-core/boot/bootutil/src/loader.c ... Archiving sys_flash_map.a Archiving sys_mfg.a Archiving sys_sysinit.a Archiving util_mem.a Linking ~/dev/myproj/bin/targets/stm32f4disc_boot/app/apps/boot/boot.elf Target successfully built: targets/stm32f4disc_boot Run the newt build stm32f4disc_blinky command to build the Blinky application: $newt build stm32f4disc_blinky Building target targets/stm32f4disc_blinky Compiling apps/blinky/src/main.c Compiling repos/apache-mynewt-core/hw/bsp/stm32f4discovery/src/sbrk.c Compiling repos/apache-mynewt-core/hw/bsp/stm32f4discovery/src/system_stm32f4xx.c Compiling repos/apache-mynewt-core/hw/bsp/stm32f4discovery/src/hal_bsp.c Assembling repos/apache-mynewt-core/hw/bsp/stm32f4discovery/src/arch/cortex_m4/startup_STM32F40x.s Compiling repos/apache-mynewt-core/hw/cmsis-core/src/cmsis_nvic.c Compiling repos/apache-mynewt-core/hw/drivers/uart/src/uart.c Compiling repos/apache-mynewt-core/hw/drivers/uart/uart_hal/src/uart_hal.c Compiling repos/apache-mynewt-core/hw/hal/src/hal_common.c Compiling repos/apache-mynewt-core/hw/hal/src/hal_flash.c ... Archiving sys_sysinit.a Archiving util_mem.a Linking ~/dev/myproj/bin/targets/stm32f4disc_blinky/app/apps/blinky/blinky.elf Target successfully built: targets/stm32f4disc_blinky Sign and Create the Blinky Application Image Run the newt create-image stm32f4disc_blinky 1.0.0 command to create and sign the application image. You may assign an arbitrary version (e.g. 1.0.0) to the image. $newt create-image stm32f4disc_blinky 1.0.0 App image succesfully generated: ~/dev/myproj/bin/targets/stm32f4disc_blinky/app/apps/blinky/blinky.img Connect to the Board Connect a USB type A to Mini-B cable from your computer to the port the board indicated on the diagram: You should see the small PWR red LED light up. Load the Bootloader and the Blinky Application Image Run the newt load stm32f4disc_boot command to load the bootloader onto the board: $newt load stm32f4disc_boot Loading bootloader Note: If you are using Windows and get an open failed or no device found error, you will need to install the usb driver. Download Zadig and run it: Select Options > List All Devices. Select STM32 STLink from the drop down menu. Select the WinUSB driver. Click Install Driver. Run the newt load stm32f4disc_boot command again. Run the newt load stm32f4disc_blinky command to load the Blinky application image onto the board. $newt load stm32f4disc_blinky Loading app image into slot 1 You should see the small green LD4 LED on the board blink! Note: If the LED does not blink, try resetting your board. If you want to erase the flash and load the image again, start a debug session, and enter mon stm32f2x mass_erase 0 at the gdb prompt: Note: The output of the debug session below is for Mac OS and Linux platforms. On Windows, openocd and gdb are started in separate Windows Command Prompt terminals, and the terminals are automatically closed when you quit gdb. In addition, the output of openocd is logged to the openocd.log file in your project's base directory instead of the terminal. $newt debug stm32f4disc_blinky [~/dev/myproj/repos/apache-mynewt-core/hw/bsp/stm32f4discovery/stm32f4discovery_debug.sh ~/dev/myproj/repos/apache-mynewt-core/hw/bsp/stm32f4discovery ~/dev/myproj/bin/targets/stm32f4disc_blinky/app/apps/blinky/blinky] Open On-Chip Debugger 0.10.0 Licensed under GNU GPL v2 For bug reports, read http://openocd.org/doc/doxygen/bugs.html Info : The selected transport took over low-level target control. The results might differ compared to plain JTAG/SWD adapter speed: 2000 kHz adapter_nsrst_delay: 100 none separate Info : Unable to match requested speed 2000 kHz, using 1800 kHz Info : Unable to match requested speed 2000 kHz, using 1800 kHz Info : clock speed 1800 kHz Info : STLINK v2 JTAG v25 API v2 SWIM v14 VID 0x0483 PID 0x374B Info : using stlink api v2 Info : Target voltage: 2.881129 Info : stm32f4x.cpu: hardware has 6 breakpoints, 4 watchpoints target halted due to debug-request, current mode: Thread ... Reading symbols from ~/dev/myproj/bin/targets/stm32f4disc_blinky/app/apps/blinky/blinky.elf...done. target halted due to debug-request, current mode: Thread xPSR: 0x41000000 pc: 0x08021e90 psp: 0x20002290 Info : accepting 'gdb' connection on tcp/3333 Info : device id = 0x10076413 Info : flash size = 1024kbytes 0x08021e90 in __WFI () at repos/apache-mynewt-core/hw/cmsis-core/src/ext/core_cmInstr.h:342 342 __ASM volatile (\"wfi\"); (gdb) mon stm32f2x mass_erase 0 stm32x mass erase complete stm32x mass erase complete (gdb)","title":"Blinky on STM32F4-Discovery"},{"location":"os/tutorials/blinky_stm32f4disc/#blinky-your-hello-world-on-stm32f4-discovery","text":"This tutorial shows you how to create, build, and run the Blinky application on the STM32F4-Discovery board.","title":"Blinky, your \"Hello World!\", on STM32F4-Discovery"},{"location":"os/tutorials/blinky_stm32f4disc/#prerequisites","text":"Meet the prerequisites listed in Project Blinky . Have a STM32F4-Discovery board. Have a USB type A to Mini-B cable. Install a patched version of OpenOCD 0.10.0 described in Install OpenOCD .","title":"Prerequisites"},{"location":"os/tutorials/blinky_stm32f4disc/#create-a-project","text":"Create a new project if you do not have an existing one. You can skip this step and proceed to create the targets if you already have a project created. Run the following commands to create a new project: $ mkdir ~/dev $ cd ~/dev $ newt new myproj Downloading project skeleton from apache/incubator-mynewt-blinky... Installing skeleton in myproj... Project myproj successfully created. $ cd myproj $ newt install apache-mynewt-core $","title":"Create a Project"},{"location":"os/tutorials/blinky_stm32f4disc/#create-the-targets","text":"Create two targets for the STM32F4-Discovery board - one for the bootloader and one for the Blinky application. Run the following newt target commands, from your project directory, to create a bootloader target. We name the target stm32f4disc_boot : $ newt target create stm32f4disc_boot $ newt target set stm32f4disc_boot app=@apache-mynewt-core/apps/boot $ newt target set stm32f4disc_boot bsp=@apache-mynewt-core/hw/bsp/stm32f4discovery $ newt target set stm32f4disc_boot build_profile=optimized Run the following newt target commands to create a target for the Blinky application. We name the target stm32f4disc_blinky : $ newt target create stm32f4disc_blinky $ newt target set stm32f4disc_blinky app=apps/blinky $ newt target set stm32f4disc_blinky bsp=@apache-mynewt-core/hw/bsp/stm32f4discovery $ newt target set stm32f4disc_blinky build_profile=debug You can run the newt target show command to verify the target settings: $ newt target show targets/my_blinky_sim app=apps/blinky bsp=@apache-mynewt-core/hw/bsp/native build_profile=debug targets/stm32f4disc_blinky app=apps/blinky bsp=@apache-mynewt-core/hw/bsp/stm32f4discovery build_profile=debug targets/stm32f4disc_boot app=@apache-mynewt-core/apps/boot bsp=@apache-mynewt-core/hw/bsp/stm32f4discovery build_profile=optimized","title":"Create the Targets"},{"location":"os/tutorials/blinky_stm32f4disc/#build-the-target-executables","text":"Run the newt build stm32f4disc_boot command to build the bootloader: $ newt build stm32f4disc_boot Building target targets/stm32f4disc_boot Compiling repos/apache-mynewt-core/boot/bootutil/src/image_ec.c Compiling repos/apache-mynewt-core/boot/bootutil/src/image_ec256.c Compiling repos/apache-mynewt-core/boot/bootutil/src/bootutil_misc.c Compiling repos/apache-mynewt-core/apps/boot/src/boot.c Compiling repos/apache-mynewt-core/boot/bootutil/src/image_rsa.c Compiling repos/apache-mynewt-core/boot/bootutil/src/image_validate.c Compiling repos/apache-mynewt-core/boot/bootutil/src/loader.c ... Archiving sys_flash_map.a Archiving sys_mfg.a Archiving sys_sysinit.a Archiving util_mem.a Linking ~/dev/myproj/bin/targets/stm32f4disc_boot/app/apps/boot/boot.elf Target successfully built: targets/stm32f4disc_boot Run the newt build stm32f4disc_blinky command to build the Blinky application: $newt build stm32f4disc_blinky Building target targets/stm32f4disc_blinky Compiling apps/blinky/src/main.c Compiling repos/apache-mynewt-core/hw/bsp/stm32f4discovery/src/sbrk.c Compiling repos/apache-mynewt-core/hw/bsp/stm32f4discovery/src/system_stm32f4xx.c Compiling repos/apache-mynewt-core/hw/bsp/stm32f4discovery/src/hal_bsp.c Assembling repos/apache-mynewt-core/hw/bsp/stm32f4discovery/src/arch/cortex_m4/startup_STM32F40x.s Compiling repos/apache-mynewt-core/hw/cmsis-core/src/cmsis_nvic.c Compiling repos/apache-mynewt-core/hw/drivers/uart/src/uart.c Compiling repos/apache-mynewt-core/hw/drivers/uart/uart_hal/src/uart_hal.c Compiling repos/apache-mynewt-core/hw/hal/src/hal_common.c Compiling repos/apache-mynewt-core/hw/hal/src/hal_flash.c ... Archiving sys_sysinit.a Archiving util_mem.a Linking ~/dev/myproj/bin/targets/stm32f4disc_blinky/app/apps/blinky/blinky.elf Target successfully built: targets/stm32f4disc_blinky","title":"Build the Target Executables"},{"location":"os/tutorials/blinky_stm32f4disc/#sign-and-create-the-blinky-application-image","text":"Run the newt create-image stm32f4disc_blinky 1.0.0 command to create and sign the application image. You may assign an arbitrary version (e.g. 1.0.0) to the image. $newt create-image stm32f4disc_blinky 1.0.0 App image succesfully generated: ~/dev/myproj/bin/targets/stm32f4disc_blinky/app/apps/blinky/blinky.img","title":"Sign and Create the Blinky Application Image"},{"location":"os/tutorials/blinky_stm32f4disc/#connect-to-the-board","text":"Connect a USB type A to Mini-B cable from your computer to the port the board indicated on the diagram: You should see the small PWR red LED light up.","title":"Connect to the Board"},{"location":"os/tutorials/blinky_stm32f4disc/#load-the-bootloader-and-the-blinky-application-image","text":"Run the newt load stm32f4disc_boot command to load the bootloader onto the board: $newt load stm32f4disc_boot Loading bootloader Note: If you are using Windows and get an open failed or no device found error, you will need to install the usb driver. Download Zadig and run it: Select Options > List All Devices. Select STM32 STLink from the drop down menu. Select the WinUSB driver. Click Install Driver. Run the newt load stm32f4disc_boot command again. Run the newt load stm32f4disc_blinky command to load the Blinky application image onto the board. $newt load stm32f4disc_blinky Loading app image into slot 1 You should see the small green LD4 LED on the board blink! Note: If the LED does not blink, try resetting your board. If you want to erase the flash and load the image again, start a debug session, and enter mon stm32f2x mass_erase 0 at the gdb prompt: Note: The output of the debug session below is for Mac OS and Linux platforms. On Windows, openocd and gdb are started in separate Windows Command Prompt terminals, and the terminals are automatically closed when you quit gdb. In addition, the output of openocd is logged to the openocd.log file in your project's base directory instead of the terminal. $newt debug stm32f4disc_blinky [~/dev/myproj/repos/apache-mynewt-core/hw/bsp/stm32f4discovery/stm32f4discovery_debug.sh ~/dev/myproj/repos/apache-mynewt-core/hw/bsp/stm32f4discovery ~/dev/myproj/bin/targets/stm32f4disc_blinky/app/apps/blinky/blinky] Open On-Chip Debugger 0.10.0 Licensed under GNU GPL v2 For bug reports, read http://openocd.org/doc/doxygen/bugs.html Info : The selected transport took over low-level target control. The results might differ compared to plain JTAG/SWD adapter speed: 2000 kHz adapter_nsrst_delay: 100 none separate Info : Unable to match requested speed 2000 kHz, using 1800 kHz Info : Unable to match requested speed 2000 kHz, using 1800 kHz Info : clock speed 1800 kHz Info : STLINK v2 JTAG v25 API v2 SWIM v14 VID 0x0483 PID 0x374B Info : using stlink api v2 Info : Target voltage: 2.881129 Info : stm32f4x.cpu: hardware has 6 breakpoints, 4 watchpoints target halted due to debug-request, current mode: Thread ... Reading symbols from ~/dev/myproj/bin/targets/stm32f4disc_blinky/app/apps/blinky/blinky.elf...done. target halted due to debug-request, current mode: Thread xPSR: 0x41000000 pc: 0x08021e90 psp: 0x20002290 Info : accepting 'gdb' connection on tcp/3333 Info : device id = 0x10076413 Info : flash size = 1024kbytes 0x08021e90 in __WFI () at repos/apache-mynewt-core/hw/cmsis-core/src/ext/core_cmInstr.h:342 342 __ASM volatile (\"wfi\"); (gdb) mon stm32f2x mass_erase 0 stm32x mass erase complete stm32x mass erase complete (gdb)","title":"Load the Bootloader and the Blinky Application Image"},{"location":"os/tutorials/blinky_windows/","text":"Project Blinky on a Windows Machine Getting your Windows machine ready for simulated target The newt tool is the build software used to build Mynewt OS images or executables for any embedded hardware device/board, including the one for the current tutorial (STM32-E407 development board from Olimex). You can run the newt tool natively on a computer running any of the three Operating System machines - OSX, Linux, or Windows. However, Mynewt OS images for a simulated target are built on the Windows machine by using Linux versions of the build software (newt)in a virtual machine on your Windows box. The Linux VM is set up by installing the Docker Toolbox. Your Windows machine will communicate with the Linux VM via transient ssh connections. You will then download a Docker image ( newtvm.exe )that allows you to run the newt commands in the Linux Docker instance. The Docker image contains: The newt command-line tool Go A multilib-capable native gcc / glibc An arm-none-eabi gcc Native gdb The sequence of events when using the Docker image is as follows: A new docker environment is created in the Linux VM. The specified command with the newtvm prefix ( newtvm newt command) is sent to the docker environment via ssh. The Linux command runs. The output from the command is sent back to Windows via ssh. The output is displayed in the Windows command prompt. Install Linux virtual machine Download the Docker Toolbox for Windows (version 1.9.0c or later) from https://www.docker.com/docker-toolbox . The Docker toolbox creates a consistently reproducible and self-contained environment in Linux. Run the Docker Toolbox installer. All the default settings are OK. You may need to add \"C:\\Program Files\\Git\\usr\\bin\" to your PATH environment variable. To add to the PATH environment variable, right-click on the Start button in the bottom left corner. Choose System -> Advanced system settings -> Environment Variables. Click on the PATH variable under \"System variables\" and click Edit to check and add it if it is not already there. Install newtvm tool From your base user (home) directory, pull or clone the latest code from the newt repository into the newt directory. It includes the executable newtvm.exe for the newtvm tool in the newtvm directory. C : \\Users\\admin> git clone https: //git-wip-us.apache.org/repos/asf/incubator-mynewt-newt newt The newtvm tool is what allows you to run programs in the Linux docker instance. Run the Docker Quickstart Terminal application inside the Docker folder under Programs. You can find it by clicking Start button -> All apps. By default, the Docker Toolbox installer creates a shortcut to this program on your desktop. Wait until you see an ASCII art whale displayed in the terminal window and the Docker prompt given. ## . ## ## ## == ## ## ## ## ## === / \"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\\___/ === ~~~ { ~~ ~~~~ ~~~ ~~~~ ~~~ ~ / ===- ~~~ \\______ o __/ \\ \\ __/ \\____\\_______/ docker is configured to use the default machine with IP 192.168.99.100 For help getting started , check out the docs at https: //docs.docker.com admin@dev1 MINGW64 ~ ( master ) $ The first time you run this, it may take several minutes to complete. You will need to run the Docker Quickstart Terminal once each time you restart your computer. Open a command prompt (e.g., Windows-R, \"cmd\", enter). You execute the newt tool commands as though you were running newt in Linux, but you prefix each command with \"newtvm\". For example: C : \\Users\\admin\\newt\\newtvm> newtvm newt help The newtvm tool will take a long time to run the first time you execute it. The delay is due to the fact that the tool must download the mynewt docker instance. You are now ready to proceed to building the image for the simulated target . Getting your Windows machine ready for hardware target When you want to produce images for actual hardware board on your Windows machine, go through the following setup procedure and then proceed to the blinky project on the Olimex board with this method. Installing some prerequisites You have to install the following if you do not have them already. The steps below indicate specific folders where each of these programs should be installed. You can choose different locations, but the remainder of this tutorial for a Windows machine assumes the specified folders. win-builds-i686 win-builds-x86_64 MSYS gcc for ARM openocd zadig git go win-builds (mingw64) 1.5 for i686 Download from http://win-builds.org/doku.php/download_and_installation_from_windows . Install at: \"C:\\win-builds-i686\". Be sure to click the i686 option (not x86_64). The defaults for all other options are OK. The installer will want to download a bunch of additional packages. They are not all necessary, but it is simplest to just accept the defaults. win-builds (mingw64) 1.5 for x86_64 Download from http://win-builds.org/doku.php/download_and_installation_from_windows . Install at \"C:\\win-builds-x86_64\" Run the installer a second time, but this time click the x86_64 option, NOT i686. The defaults for all other options are OK. MSYS Start your download from http://sourceforge.net/projects/mingw-w64/files/External%20binary%20packages%20%28Win64%20hosted%29/MSYS%20%2832-bit%29/MSYS-20111123.zip Unzip to \"C:\\msys\" gcc for ARM, 4.9.3 Download the Windows installer from https://launchpad.net/gcc-arm-embedded/+download and install at \"C:\\Program Files (x86)\\GNU Tools ARM Embedded\\4.9 2015q3\". OpenOCD 0.8.0 Download OpenOCD 0.8.0 from http://www.freddiechopin.info/en/download/category/4-openocd . Unzip to \"C:\\openocd\". Zadig 2.1.2 Download it from http://zadig.akeo.ie and install it at \"C:\\zadig\". Git Click on https://git-scm.com/download/win to start the download. Install at \"C:\\Program Files (x86)\\Git\". Specify the \"Use Git from the Windows Command Prompt\" option. The defaults for all other options are OK. Go Download the release for Microsoft Windows from https://golang.org/dl/ and install it \"C:\\Go\". Creating local repository The directory structure must be first readied for using Go. Go code must be kept inside a workspace. A workspace is a directory hierarchy with three directories at its root: src contains Go source files organized into packages (one package per directory), pkg contains package objects, and bin contains executable commands. The GOPATH environment variable specifies the location of your workspace. First create a 'dev' directory and then a 'go' directory under it. Set the GOPATH environment variable to this directory and then proceed to create the directory for cloning the newt tool repository. $ cd c: \\ $ mkdir dev\\go $ cd dev\\go Set the following user environment variables using the steps outlined here. * GOPATH: C:\\dev\\go * PATH: C:\\Program Files ( x86 ) \\GNU Tools ARM Embedded\\ 4.9 2015 q3\\bin ; %GOPATH%\\bin ; C:\\win-builds-x86_64\\bin ; C:\\win-builds-i686\\bin ; C:\\msys\\bin Steps: Right-click the start button Click \"Control panel\" Click \"System and Security\" Click \"System\" Click \"Advanced system settings\" in the left panel Click the \"Envoronment Variables...\" button There will be two sets of environment variables: user variables in the upper half of the screen, and system variables in the lower half. Configuring the user variables is recommended and tested (though system variables will work as well). Next, install godep. Note that the following command produces no output. $ go get github . com/tools/godep Set up the repository for the package building tool \"newt\" on your local machine. First create the appropriate directory for it and then clone the newt tool repository from the online apache repository (or its github.com mirror) into this newly created directory. Check the contents of the directory. $ go get git-wip-us . apache . org/repos/asf/incubator-mynewt-newt . git/newt $ dir bin pkg src $ dir src git-wip-us . apache . org github . com gopkg . in $ dir newt $ cd newt $ dir Godeps README . md coding_style . txt newt . go LICENSE cli design . txt Check that newt is in place. $ dir $GOPATH\\src\\git-wip-us . apache . org\\repos\\asf\\incubator-mynewt-newt . git\\newt Godeps README . md coding_style . txt newt . go LICENSE cli design . txt Building the newt tool You will use Go to run the newt.go program to build the newt tool. The command used is go install which compiles and writes the resulting executable to an output file named newt . It installs the results along with its dependencies in $GOPATH/bin. $ go install $ ls \"$GOPATH\" /bin/ godep incubator-mynewt-newt . git newt Try running newt using the compiled binary. For example, check for the version number by typing 'newt version'. See all the possible commands available to a user of newt by typing 'newt -h'. Note: If you are going to be be modifying the newt tool itself often and wish to compile the program every time you call it, you may want to define the newt environment variable that allows you to execute the command via %newt% . Use set newt=go run %GOPATH%\\src\\github.com\\mynewt\\newt\\newt.go or set it from the GUI. Here, you use go run which runs the compiled binary directly without producing an executable. $ newt version Newt version: 1.0 $ newt -h Newt allows you to create your own embedded project based on the Mynewt operating system . Newt provides both build and package management in a single tool , which allows you to compose an embedded workspace , and set of projects , and then build the necessary artifacts from those projects . For more information on the Mynewt operating system , please visit https : //www.github.com/mynewt/documentation. Please use the newt help command , and specify the name of the command you want help for , for help on how to use a specific command Usage : newt [ flags ] newt [ command ] Examples : newt newt help [ <command-name> ] For help on <command-name> . If not specified , print this message . Available Commands: version Display the Newt version number . target Set and view target information egg Commands to list and inspect eggs on a nest nest Commands to manage nests & clutches ( remote egg repositories ) help Help about any command Flags : -h , --help= false : help for newt -l , --loglevel= \"WARN\" : Log level , defaults to WARN . -q , --quiet= false : Be quiet ; only display error output . -s , --silent= false : Be silent ; don't output anything . -v , --verbose= false : Enable verbose output when executing commands . Use \"newt help [command]\" for more information about a command . Without creating a project repository you can't do a whole lot with the Newt tool. So you'll have to wait till you have downloaded a nest to try out the tool. Getting the debugger ready Use Zadig to configure the USB driver for your Olimex debugger. If your debugger is already set up, you can skip this step. Plug in your Olimex debugger. Start Zadig. Check the Options -> List All Devices checkbox. Select \"Olimex OpenOCD JTAG ARM-USB-TINY-H\" in the dropdown menu. Select the \"WinUSB\" driver. Click the \"Install Driver\" button. Proceed to the section on how to make an LED blink section.","title":"Blinky windows"},{"location":"os/tutorials/blinky_windows/#project-blinky-on-a-windows-machine","text":"","title":"Project Blinky on a Windows Machine"},{"location":"os/tutorials/blinky_windows/#getting-your-windows-machine-ready-for-simulated-target","text":"The newt tool is the build software used to build Mynewt OS images or executables for any embedded hardware device/board, including the one for the current tutorial (STM32-E407 development board from Olimex). You can run the newt tool natively on a computer running any of the three Operating System machines - OSX, Linux, or Windows. However, Mynewt OS images for a simulated target are built on the Windows machine by using Linux versions of the build software (newt)in a virtual machine on your Windows box. The Linux VM is set up by installing the Docker Toolbox. Your Windows machine will communicate with the Linux VM via transient ssh connections. You will then download a Docker image ( newtvm.exe )that allows you to run the newt commands in the Linux Docker instance. The Docker image contains: The newt command-line tool Go A multilib-capable native gcc / glibc An arm-none-eabi gcc Native gdb The sequence of events when using the Docker image is as follows: A new docker environment is created in the Linux VM. The specified command with the newtvm prefix ( newtvm newt command) is sent to the docker environment via ssh. The Linux command runs. The output from the command is sent back to Windows via ssh. The output is displayed in the Windows command prompt.","title":"Getting your Windows machine ready for simulated target"},{"location":"os/tutorials/blinky_windows/#install-linux-virtual-machine","text":"Download the Docker Toolbox for Windows (version 1.9.0c or later) from https://www.docker.com/docker-toolbox . The Docker toolbox creates a consistently reproducible and self-contained environment in Linux. Run the Docker Toolbox installer. All the default settings are OK. You may need to add \"C:\\Program Files\\Git\\usr\\bin\" to your PATH environment variable. To add to the PATH environment variable, right-click on the Start button in the bottom left corner. Choose System -> Advanced system settings -> Environment Variables. Click on the PATH variable under \"System variables\" and click Edit to check and add it if it is not already there.","title":"Install Linux virtual machine"},{"location":"os/tutorials/blinky_windows/#install-newtvm-tool","text":"From your base user (home) directory, pull or clone the latest code from the newt repository into the newt directory. It includes the executable newtvm.exe for the newtvm tool in the newtvm directory. C : \\Users\\admin> git clone https: //git-wip-us.apache.org/repos/asf/incubator-mynewt-newt newt The newtvm tool is what allows you to run programs in the Linux docker instance. Run the Docker Quickstart Terminal application inside the Docker folder under Programs. You can find it by clicking Start button -> All apps. By default, the Docker Toolbox installer creates a shortcut to this program on your desktop. Wait until you see an ASCII art whale displayed in the terminal window and the Docker prompt given. ## . ## ## ## == ## ## ## ## ## === / \"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\\___/ === ~~~ { ~~ ~~~~ ~~~ ~~~~ ~~~ ~ / ===- ~~~ \\______ o __/ \\ \\ __/ \\____\\_______/ docker is configured to use the default machine with IP 192.168.99.100 For help getting started , check out the docs at https: //docs.docker.com admin@dev1 MINGW64 ~ ( master ) $ The first time you run this, it may take several minutes to complete. You will need to run the Docker Quickstart Terminal once each time you restart your computer. Open a command prompt (e.g., Windows-R, \"cmd\", enter). You execute the newt tool commands as though you were running newt in Linux, but you prefix each command with \"newtvm\". For example: C : \\Users\\admin\\newt\\newtvm> newtvm newt help The newtvm tool will take a long time to run the first time you execute it. The delay is due to the fact that the tool must download the mynewt docker instance. You are now ready to proceed to building the image for the simulated target .","title":"Install newtvm tool"},{"location":"os/tutorials/blinky_windows/#getting-your-windows-machine-ready-for-hardware-target","text":"When you want to produce images for actual hardware board on your Windows machine, go through the following setup procedure and then proceed to the blinky project on the Olimex board with this method.","title":"Getting your Windows machine ready for hardware target"},{"location":"os/tutorials/blinky_windows/#installing-some-prerequisites","text":"You have to install the following if you do not have them already. The steps below indicate specific folders where each of these programs should be installed. You can choose different locations, but the remainder of this tutorial for a Windows machine assumes the specified folders. win-builds-i686 win-builds-x86_64 MSYS gcc for ARM openocd zadig git go win-builds (mingw64) 1.5 for i686 Download from http://win-builds.org/doku.php/download_and_installation_from_windows . Install at: \"C:\\win-builds-i686\". Be sure to click the i686 option (not x86_64). The defaults for all other options are OK. The installer will want to download a bunch of additional packages. They are not all necessary, but it is simplest to just accept the defaults. win-builds (mingw64) 1.5 for x86_64 Download from http://win-builds.org/doku.php/download_and_installation_from_windows . Install at \"C:\\win-builds-x86_64\" Run the installer a second time, but this time click the x86_64 option, NOT i686. The defaults for all other options are OK. MSYS Start your download from http://sourceforge.net/projects/mingw-w64/files/External%20binary%20packages%20%28Win64%20hosted%29/MSYS%20%2832-bit%29/MSYS-20111123.zip Unzip to \"C:\\msys\" gcc for ARM, 4.9.3 Download the Windows installer from https://launchpad.net/gcc-arm-embedded/+download and install at \"C:\\Program Files (x86)\\GNU Tools ARM Embedded\\4.9 2015q3\". OpenOCD 0.8.0 Download OpenOCD 0.8.0 from http://www.freddiechopin.info/en/download/category/4-openocd . Unzip to \"C:\\openocd\". Zadig 2.1.2 Download it from http://zadig.akeo.ie and install it at \"C:\\zadig\". Git Click on https://git-scm.com/download/win to start the download. Install at \"C:\\Program Files (x86)\\Git\". Specify the \"Use Git from the Windows Command Prompt\" option. The defaults for all other options are OK. Go Download the release for Microsoft Windows from https://golang.org/dl/ and install it \"C:\\Go\".","title":"Installing some prerequisites"},{"location":"os/tutorials/blinky_windows/#creating-local-repository","text":"The directory structure must be first readied for using Go. Go code must be kept inside a workspace. A workspace is a directory hierarchy with three directories at its root: src contains Go source files organized into packages (one package per directory), pkg contains package objects, and bin contains executable commands. The GOPATH environment variable specifies the location of your workspace. First create a 'dev' directory and then a 'go' directory under it. Set the GOPATH environment variable to this directory and then proceed to create the directory for cloning the newt tool repository. $ cd c: \\ $ mkdir dev\\go $ cd dev\\go Set the following user environment variables using the steps outlined here. * GOPATH: C:\\dev\\go * PATH: C:\\Program Files ( x86 ) \\GNU Tools ARM Embedded\\ 4.9 2015 q3\\bin ; %GOPATH%\\bin ; C:\\win-builds-x86_64\\bin ; C:\\win-builds-i686\\bin ; C:\\msys\\bin Steps: Right-click the start button Click \"Control panel\" Click \"System and Security\" Click \"System\" Click \"Advanced system settings\" in the left panel Click the \"Envoronment Variables...\" button There will be two sets of environment variables: user variables in the upper half of the screen, and system variables in the lower half. Configuring the user variables is recommended and tested (though system variables will work as well). Next, install godep. Note that the following command produces no output. $ go get github . com/tools/godep Set up the repository for the package building tool \"newt\" on your local machine. First create the appropriate directory for it and then clone the newt tool repository from the online apache repository (or its github.com mirror) into this newly created directory. Check the contents of the directory. $ go get git-wip-us . apache . org/repos/asf/incubator-mynewt-newt . git/newt $ dir bin pkg src $ dir src git-wip-us . apache . org github . com gopkg . in $ dir newt $ cd newt $ dir Godeps README . md coding_style . txt newt . go LICENSE cli design . txt Check that newt is in place. $ dir $GOPATH\\src\\git-wip-us . apache . org\\repos\\asf\\incubator-mynewt-newt . git\\newt Godeps README . md coding_style . txt newt . go LICENSE cli design . txt","title":"Creating local repository"},{"location":"os/tutorials/blinky_windows/#building-the-newt-tool","text":"You will use Go to run the newt.go program to build the newt tool. The command used is go install which compiles and writes the resulting executable to an output file named newt . It installs the results along with its dependencies in $GOPATH/bin. $ go install $ ls \"$GOPATH\" /bin/ godep incubator-mynewt-newt . git newt Try running newt using the compiled binary. For example, check for the version number by typing 'newt version'. See all the possible commands available to a user of newt by typing 'newt -h'. Note: If you are going to be be modifying the newt tool itself often and wish to compile the program every time you call it, you may want to define the newt environment variable that allows you to execute the command via %newt% . Use set newt=go run %GOPATH%\\src\\github.com\\mynewt\\newt\\newt.go or set it from the GUI. Here, you use go run which runs the compiled binary directly without producing an executable. $ newt version Newt version: 1.0 $ newt -h Newt allows you to create your own embedded project based on the Mynewt operating system . Newt provides both build and package management in a single tool , which allows you to compose an embedded workspace , and set of projects , and then build the necessary artifacts from those projects . For more information on the Mynewt operating system , please visit https : //www.github.com/mynewt/documentation. Please use the newt help command , and specify the name of the command you want help for , for help on how to use a specific command Usage : newt [ flags ] newt [ command ] Examples : newt newt help [ <command-name> ] For help on <command-name> . If not specified , print this message . Available Commands: version Display the Newt version number . target Set and view target information egg Commands to list and inspect eggs on a nest nest Commands to manage nests & clutches ( remote egg repositories ) help Help about any command Flags : -h , --help= false : help for newt -l , --loglevel= \"WARN\" : Log level , defaults to WARN . -q , --quiet= false : Be quiet ; only display error output . -s , --silent= false : Be silent ; don't output anything . -v , --verbose= false : Enable verbose output when executing commands . Use \"newt help [command]\" for more information about a command . Without creating a project repository you can't do a whole lot with the Newt tool. So you'll have to wait till you have downloaded a nest to try out the tool.","title":"Building the newt tool"},{"location":"os/tutorials/blinky_windows/#getting-the-debugger-ready","text":"Use Zadig to configure the USB driver for your Olimex debugger. If your debugger is already set up, you can skip this step. Plug in your Olimex debugger. Start Zadig. Check the Options -> List All Devices checkbox. Select \"Olimex OpenOCD JTAG ARM-USB-TINY-H\" in the dropdown menu. Select the \"WinUSB\" driver. Click the \"Install Driver\" button. Proceed to the section on how to make an LED blink section.","title":"Getting the debugger ready"},{"location":"os/tutorials/define_target/","text":"How to Define a Target What newt commands to use?","title":"Define target"},{"location":"os/tutorials/define_target/#how-to-define-a-target","text":"What newt commands to use?","title":"How to Define a Target"},{"location":"os/tutorials/eddystone/","text":"BLE Eddystone Eddystone Beacon Protocol A beaconing device announces its presence to the world by broadcasting advertisements. The Eddystone protocol is built on top of the standard BLE advertisement specification. Eddystone supports multiple data packet types Eddystone-UID: a unique, static ID with a 10-byte Namespace component and a 6-byte Instance component. Eddystone-URL: a compressed URL that, once parsed and decompressed, is directly usable by the client. Eddystone-TLM: \"telemetry\" packets that are broadcast alongside the Eddystone-UID or Eddystone-URL packets and contains beacon\u2019s \u201chealth status\u201d (e.g., battery life). Eddystone-EID to broadcast an ephemeral identifier that changes every few minutes and allow only parties that can resolve the identifier to use the beacon. This page describes the Eddystone open beacon format developed by Google. Apache Mynewt currently supports Eddystone-UID and Eddystone-URL formats only. This tutorial will explain how to get an Eddystone-URL beacon going on a peripheral device. Configuration Use the following function to configure your NimBLE device to send Eddystone-URL beacons: int ble_eddystone_set_adv_data_url ( struct ble_hs_adv_fields *adv_fields , uint8_t url_scheme , char *url_body , uint8_t url_body_len , uint8_t url_suffix ) This function's parameters are documented below. Parameter Purpose adv_fields The base advertisement fields to transform into an eddystone beacon. url_scheme The prefix of the URL; one of the BLE_EDDYSTONE_URL_SCHEME values from ble_eddystone.h url_body The middle of the url specified within \"\". url_body_len The string length of the url_body argument. url_suffix The suffix of the URL; one of the BLE_EDDYSTONE_URL_SUFFIX values from ble_eddystone.h Modify bleprph To demonstrate how the above function is used, we will now modify the bleprph example application to send Eddystone beacons. For some background behind the bleprph app, we recommend you take a look at the bleprph project tutorial . If you plan on making these modifications yourself, it might be a good idea to copy bleprph to your local repository and work with the copy. In general, you should avoid changing a package that newt downloads, as you will lose your changes the next time you upgrade the package. bleprph sets its advertisement data and begins advertising as follows ( main.c ): static void bleprph_advertise ( void ) { struct ble_gap_adv_params adv_params ; struct ble_hs_adv_fields fields ; const char *name ; int rc ; /** * Set the advertisement data included in our advertisements: * o Flags (indicates advertisement type and other general info). * o Advertising tx power. * o Device name. * o 16-bit service UUIDs (alert notifications). */ memset ( &fields , 0 , sizeof fields ); /* Advertise two flags: * o Discoverability in forthcoming advertisement (general) * o BLE-only (BR/EDR unsupported). */ fields . flags = BLE_HS_ADV_F_DISC_GEN | BLE_HS_ADV_F_BREDR_UNSUP ; /* Indicate that the TX power level field should be included; have the * stack fill this value automatically. This is done by assiging the * special value BLE_HS_ADV_TX_PWR_LVL_AUTO. */ fields . tx_pwr_lvl_is_present = 1 ; fields . tx_pwr_lvl = BLE_HS_ADV_TX_PWR_LVL_AUTO ; name = ble_svc_gap_device_name (); fields . name = ( uint8_t * ) name ; fields . name_len = strlen ( name ); fields . name_is_complete = 1 ; fields . uuids16 = ( ble_uuid16_t []){ BLE_UUID16_INIT ( GATT_SVR_SVC_ALERT_UUID ) }; fields . num_uuids16 = 1 ; fields . uuids16_is_complete = 1 ; rc = ble_gap_adv_set_fields ( &fields ); if ( rc != 0 ) { BLEPRPH_LOG ( ERROR , \"error setting advertisement data; rc=%d\\n\" , rc ); return ; } /* Begin advertising. */ memset ( &adv_params , 0 , sizeof adv_params ); adv_params . conn_mode = BLE_GAP_CONN_MODE_UND ; adv_params . disc_mode = BLE_GAP_DISC_MODE_GEN ; rc = ble_gap_adv_start ( BLE_OWN_ADDR_PUBLIC , NULL , BLE_HS_FOREVER , &adv_params , bleprph_gap_event , NULL ); if ( rc != 0 ) { BLEPRPH_LOG ( ERROR , \"error enabling advertisement; rc=%d\\n\" , rc ); return ; } } The call to ble_gap_adv_set_fields() configures the device with normal (non-Eddystone) advertisements; the call to ble_gap_adv_start() tells the NimBLE stack to start broadcasting. We are now going to create an Eddystone app by making the following changes: Call ble_eddystone_set_adv_data() instead of ble_gap_adv_set_fields() . The tutorial shows how to emit \"`https://mynewt.apache.org\". Remove advertisement data such as device name, flags, tx levels etc. that are not required. Remove unnecessary local variables e.g. name pointer. Modify the call to ble_gap_adv_start() such that the device is non-discoverable and non-connectable. static void bleprph_advertise ( void ) { struct ble_gap_adv_params adv_params ; struct ble_hs_adv_fields fields ; int rc ; /** * Remove the advertisement data typically included in our advertisements: * o Flags (indicates advertisement type and other general info). * o Advertising tx power. * o Device name. * o 16-bit service UUIDs (alert notifications). */ memset ( &fields , 0 , sizeof fields ); /* No flags are needed for Eddystone URL. Remove all from default app.*/ rc = ble_eddystone_set_adv_data_url ( &fields , BLE_EDDYSTONE_URL_SCHEME_HTTPS , \"mynewt.apache\" , 13 , BLE_EDDYSTONE_URL_SUFFIX_ORG ); if ( rc != 0 ) { BLEPRPH_LOG ( ERROR , \"error setting eddystone advertisement data; rc=%d\\n\" , rc ); return ; } /* Begin advertising. */ memset ( &adv_params , 0 , sizeof adv_params ); adv_params . conn_mode = BLE_GAP_CONN_MODE_NON ; adv_params . disc_mode = BLE_GAP_DISC_MODE_NON ; rc = ble_gap_adv_start ( BLE_OWN_ADDR_PUBLIC , NULL , BLE_HS_FOREVER , &adv_params , bleprph_gap_event , NULL ); if ( rc != 0 ) { BLEPRPH_LOG ( ERROR , \"error enabling advertisement; rc=%d\\n\" , rc ); return ; } } Also include the header file for the eddystone beacon ble_eddystone.h in the app's main.c file. #include \"host/ble_eddystone.h\" If you have copied the bleprph app into your local repository then make sure that the pkg.yml for the app has the @apache-mynewt-core/ prefix; otherwise the package dependencies will not be resolved correctly. pkg.deps: - \"@apache-mynewt-core/boot/split\" - \"@apache-mynewt-core/kernel/os\" <snip> Finally, enable the BLE_EDDYSTONE sysconfig in the syscfg.yml of either your target or your app. syscfg.vals: <snip> BLE_EDDYSTONE: 1 Now when you run this app on your board, you should be able to see it with all your Eddystone-aware devices.","title":"BLE Eddystone"},{"location":"os/tutorials/eddystone/#ble-eddystone","text":"","title":"BLE Eddystone"},{"location":"os/tutorials/eddystone/#eddystone-beacon-protocol","text":"A beaconing device announces its presence to the world by broadcasting advertisements. The Eddystone protocol is built on top of the standard BLE advertisement specification. Eddystone supports multiple data packet types Eddystone-UID: a unique, static ID with a 10-byte Namespace component and a 6-byte Instance component. Eddystone-URL: a compressed URL that, once parsed and decompressed, is directly usable by the client. Eddystone-TLM: \"telemetry\" packets that are broadcast alongside the Eddystone-UID or Eddystone-URL packets and contains beacon\u2019s \u201chealth status\u201d (e.g., battery life). Eddystone-EID to broadcast an ephemeral identifier that changes every few minutes and allow only parties that can resolve the identifier to use the beacon. This page describes the Eddystone open beacon format developed by Google. Apache Mynewt currently supports Eddystone-UID and Eddystone-URL formats only. This tutorial will explain how to get an Eddystone-URL beacon going on a peripheral device.","title":"Eddystone Beacon Protocol"},{"location":"os/tutorials/eddystone/#configuration","text":"Use the following function to configure your NimBLE device to send Eddystone-URL beacons: int ble_eddystone_set_adv_data_url ( struct ble_hs_adv_fields *adv_fields , uint8_t url_scheme , char *url_body , uint8_t url_body_len , uint8_t url_suffix ) This function's parameters are documented below. Parameter Purpose adv_fields The base advertisement fields to transform into an eddystone beacon. url_scheme The prefix of the URL; one of the BLE_EDDYSTONE_URL_SCHEME values from ble_eddystone.h url_body The middle of the url specified within \"\". url_body_len The string length of the url_body argument. url_suffix The suffix of the URL; one of the BLE_EDDYSTONE_URL_SUFFIX values from ble_eddystone.h","title":"Configuration"},{"location":"os/tutorials/eddystone/#modify-bleprph","text":"To demonstrate how the above function is used, we will now modify the bleprph example application to send Eddystone beacons. For some background behind the bleprph app, we recommend you take a look at the bleprph project tutorial . If you plan on making these modifications yourself, it might be a good idea to copy bleprph to your local repository and work with the copy. In general, you should avoid changing a package that newt downloads, as you will lose your changes the next time you upgrade the package. bleprph sets its advertisement data and begins advertising as follows ( main.c ): static void bleprph_advertise ( void ) { struct ble_gap_adv_params adv_params ; struct ble_hs_adv_fields fields ; const char *name ; int rc ; /** * Set the advertisement data included in our advertisements: * o Flags (indicates advertisement type and other general info). * o Advertising tx power. * o Device name. * o 16-bit service UUIDs (alert notifications). */ memset ( &fields , 0 , sizeof fields ); /* Advertise two flags: * o Discoverability in forthcoming advertisement (general) * o BLE-only (BR/EDR unsupported). */ fields . flags = BLE_HS_ADV_F_DISC_GEN | BLE_HS_ADV_F_BREDR_UNSUP ; /* Indicate that the TX power level field should be included; have the * stack fill this value automatically. This is done by assiging the * special value BLE_HS_ADV_TX_PWR_LVL_AUTO. */ fields . tx_pwr_lvl_is_present = 1 ; fields . tx_pwr_lvl = BLE_HS_ADV_TX_PWR_LVL_AUTO ; name = ble_svc_gap_device_name (); fields . name = ( uint8_t * ) name ; fields . name_len = strlen ( name ); fields . name_is_complete = 1 ; fields . uuids16 = ( ble_uuid16_t []){ BLE_UUID16_INIT ( GATT_SVR_SVC_ALERT_UUID ) }; fields . num_uuids16 = 1 ; fields . uuids16_is_complete = 1 ; rc = ble_gap_adv_set_fields ( &fields ); if ( rc != 0 ) { BLEPRPH_LOG ( ERROR , \"error setting advertisement data; rc=%d\\n\" , rc ); return ; } /* Begin advertising. */ memset ( &adv_params , 0 , sizeof adv_params ); adv_params . conn_mode = BLE_GAP_CONN_MODE_UND ; adv_params . disc_mode = BLE_GAP_DISC_MODE_GEN ; rc = ble_gap_adv_start ( BLE_OWN_ADDR_PUBLIC , NULL , BLE_HS_FOREVER , &adv_params , bleprph_gap_event , NULL ); if ( rc != 0 ) { BLEPRPH_LOG ( ERROR , \"error enabling advertisement; rc=%d\\n\" , rc ); return ; } } The call to ble_gap_adv_set_fields() configures the device with normal (non-Eddystone) advertisements; the call to ble_gap_adv_start() tells the NimBLE stack to start broadcasting. We are now going to create an Eddystone app by making the following changes: Call ble_eddystone_set_adv_data() instead of ble_gap_adv_set_fields() . The tutorial shows how to emit \"`https://mynewt.apache.org\". Remove advertisement data such as device name, flags, tx levels etc. that are not required. Remove unnecessary local variables e.g. name pointer. Modify the call to ble_gap_adv_start() such that the device is non-discoverable and non-connectable. static void bleprph_advertise ( void ) { struct ble_gap_adv_params adv_params ; struct ble_hs_adv_fields fields ; int rc ; /** * Remove the advertisement data typically included in our advertisements: * o Flags (indicates advertisement type and other general info). * o Advertising tx power. * o Device name. * o 16-bit service UUIDs (alert notifications). */ memset ( &fields , 0 , sizeof fields ); /* No flags are needed for Eddystone URL. Remove all from default app.*/ rc = ble_eddystone_set_adv_data_url ( &fields , BLE_EDDYSTONE_URL_SCHEME_HTTPS , \"mynewt.apache\" , 13 , BLE_EDDYSTONE_URL_SUFFIX_ORG ); if ( rc != 0 ) { BLEPRPH_LOG ( ERROR , \"error setting eddystone advertisement data; rc=%d\\n\" , rc ); return ; } /* Begin advertising. */ memset ( &adv_params , 0 , sizeof adv_params ); adv_params . conn_mode = BLE_GAP_CONN_MODE_NON ; adv_params . disc_mode = BLE_GAP_DISC_MODE_NON ; rc = ble_gap_adv_start ( BLE_OWN_ADDR_PUBLIC , NULL , BLE_HS_FOREVER , &adv_params , bleprph_gap_event , NULL ); if ( rc != 0 ) { BLEPRPH_LOG ( ERROR , \"error enabling advertisement; rc=%d\\n\" , rc ); return ; } } Also include the header file for the eddystone beacon ble_eddystone.h in the app's main.c file. #include \"host/ble_eddystone.h\" If you have copied the bleprph app into your local repository then make sure that the pkg.yml for the app has the @apache-mynewt-core/ prefix; otherwise the package dependencies will not be resolved correctly. pkg.deps: - \"@apache-mynewt-core/boot/split\" - \"@apache-mynewt-core/kernel/os\" <snip> Finally, enable the BLE_EDDYSTONE sysconfig in the syscfg.yml of either your target or your app. syscfg.vals: <snip> BLE_EDDYSTONE: 1 Now when you run this app on your board, you should be able to see it with all your Eddystone-aware devices.","title":"Modify bleprph"},{"location":"os/tutorials/event_queue/","text":"How to Use Event Queues to Manage Multiple Events Introduction The event queue mechanism allows you to serialize incoming events for your task. You can use it to get information about hardware interrupts, callout expirations, and messages from other tasks. The benefit of using events for inter-task communication is that it can reduce the number of resources that need to be shared and locked. The benefit of processing interrupts in a task context instead of the interrupt context is that other interrupts and high priority tasks are not blocked waiting for the interrupt handler to complete processing. A task can also access other OS facilities and sleep. This tutorial assumes that you have read about Event Queues , the Hardware Abstraction Layer , and OS Callouts in the OS User's Guide. This tutorial shows you how to create an application that uses events for: Inter-task communication OS callouts for timer expiration GPIO interrupts It also shows you how to: Use the Mynewt default event queue and application main task to process your events. Create a dedicated event queue and task for your events. To reduce an application's memory requirement, we recommend that you use the Mynewt default event queue if your application or package does not have real-time timing requirements. Prerequisites Ensure that you have met the following prerequisites before continuing with this tutorial: Install the newt tool. Install the newtmgr tool. Have Internet connectivity to fetch remote Mynewt components. Install the compiler tools to support native compiling to build the project this tutorial creates. Have a cable to establish a serial USB connection between the board and the laptop. Example Application In this example, you will write an application, for the Nordic nRF52 board, that uses events from three input sources to toggle three GPIO outputs and light up the LEDs. If you are using a different board, you will need to adjust the GPIO pin numbers in the code example. The application handles events from three sources on two event queues: Events generated by an application task at periodic intervals are added to the Mynewt default event queue. OS callouts for timer events are added to the my_timer_interrupt_eventq event queue. GPIO interrupt events are added to the my_timer_interrupt_eventq event queue. Create the Project Follow the instructions in the nRF52 tutorial to create a project. Create the Application Create the pkg.yml file for the application: pkg.name: apps/eventq_example pkg.type: app pkg.deps: - kernel/os - hw/hal - sys/console/stub Application Task Generated Events The application creates a task that generates events, at periodic intervals, to toggle the LED at pin TASK_LED . The event is queued on the Mynewt default event queue and is processed in the context of the application main task. Declare and initialize the gen_task_ev event with the my_ev_cb() callback function to process the event: /* Callback function for application task event */ static void my_ev_cb ( struct os_event * ); /* Initialize the event with the callback function */ static struct os_event gen_task_ev = { . ev_cb = my_ev_cb , }; Implement the my_ev_cb() callback function to process a task generated event and toggle the LED at pin TASK_LED : /* LED 1 (P0.17 on the board) */ #define TASK_LED 17 /* * Event callback function for events generated by gen_task. It toggles * the LED at pin TASK_LED. */ static void my_ev_cb ( struct os_event *ev ) { assert ( ev ); hal_gpio_toggle ( TASK_LED ); return ; } Create a task that generates an event at periodic intervals and adds, using the os_eventq_put() function, the event to the Mynewt default event queue: #define GEN_TASK_PRIO 3 #define GEN_TASK_STACK_SZ 512 static os_stack_t gen_task_stack [ GEN_TASK_STACK_SZ ]; static struct os_task gen_task_str ; /* * Task handler to generate an event to toggle the LED at pin TASK_LED. * The event is added to the Mynewt default event queue. */ static void gen_task ( void *arg ) { while ( 1 ) { os_time_delay ( OS_TICKS_PER_SEC / 4 ); os_eventq_put ( os_eventq_dflt_get (), &gen_task_ev ); } } static void init_tasks ( void ) { /* Create a task to generate events to toggle the LED at pin TASK_LED */ os_task_init ( &gen_task_str , \"gen_task\" , gen_task , NULL , GEN_TASK_PRIO , OS_WAIT_FOREVER , gen_task_stack , GEN_TASK_STACK_SZ ); ... } Implement the application main() function to call the os_eventq_run() function to dequeue an event from the Mynewt default event queue and call the callback function to process the event. int main ( int argc , char **argv ) { sysinit (); init_tasks (); while ( 1 ) { os_eventq_run ( os_eventq_dflt_get ()); } assert ( 0 ); } OS Callout Timer Events Set up OS callout timer events. For this example, we use a dedicated event queue for timer events to show you how to create a dedicated event queue and a task to process the events. Implement the my_timer_ev_cb() callback function to process a timer event and toggle the LED at pin CALLOUT_LED : /* LED 2 (P0.18 on the board) */ #define CALLOUT_LED 18 /* The timer callout */ static struct os_callout my_callout ; /* * Event callback function for timer events. It toggles the LED at pin CALLOUT_LED. */ static void my_timer_ev_cb ( struct os_event *ev ) { assert ( ev != NULL ); hal_gpio_toggle ( CALLOUT_LED ); os_callout_reset ( &my_callout , OS_TICKS_PER_SEC / 2 ); } In the init_tasks() function, initialize the my_timer_interrupt_eventq event queue, create a task to process events from the queue, and initialize the OS callout for the timer: #define MY_TIMER_INTERRUPT_TASK_PRIO 4 #define MY_TIMER_INTERRUPT_TASK_STACK_SZ 512 static os_stack_t my_timer_interrupt_task_stack [ MY_TIMER_INTERRUPT_TASK_STACK_SZ ]; static struct os_task my_timer_interrupt_task_str ; static void init_tasks ( void ) { /* Use a dedicate event queue for timer and interrupt events */ os_eventq_init ( &my_timer_interrupt_eventq ); /* * Create the task to process timer and interrupt events from the * my_timer_interrupt_eventq event queue. */ os_task_init ( &my_timer_interrupt_task_str , \"timer_interrupt_task\" , my_timer_interrupt_task , NULL , MY_TIMER_INTERRUPT_TASK_PRIO , OS_WAIT_FOREVER , my_timer_interrupt_task_stack , MY_TIMER_INTERRUPT_TASK_STACK_SZ ); /* * Initialize the callout for a timer event. * The my_timer_ev_cb callback function processes the timer events. */ os_callout_init ( &my_callout , &my_timer_interrupt_eventq , my_timer_ev_cb , NULL ); os_callout_reset ( &my_callout , OS_TICKS_PER_SEC ); } Implement the my_timer_interrupt_task() task handler to dispatch events from the my_timer_interrupt_eventq event queue: static void my_timer_interrupt_task ( void *arg ) { while ( 1 ) { os_eventq_run ( &my_timer_interrupt_eventq ); } } Interrupt Events The application toggles the LED each time button 1 on the board is pressed. The interrupt handler generates an event when the GPIO for button 1 (P0.13) changes state. The events are added to the my_timer_interrupt_eventq event queue, the same queue as the timer events. Declare and initialize the gpio_ev event with the my_interrupt_ev_cb() callback function to process the event: static struct os_event gpio_ev { . ev_cb = my_interrupt_ev_cb , }; Implement the my_interrupt_ev_cb() callback function to process an interrupt event and toggle the LED at pin GPIO_LED : /* LED 3 (P0.19 on the board) */ #define GPIO_LED 19 /* * Event callback function for interrupt events. It toggles the LED at pin GPIO_LED. */ static void my_interrupt_ev_cb ( struct os_event *ev ) { assert ( ev != NULL ); hal_gpio_toggle ( GPIO_LED ); } Implement the my_gpio_irq() handler to post an interrupt event to the my_timer_interrupt_eventq event queue: static void my_gpio_irq ( void *arg ) { os_eventq_put ( &my_timer_interrupt_eventq , &gpio_ev ); } In the init_tasks() function, add the code to set up and enable the GPIO input pin for the button and initialize the GPIO output pins for the LEDs: /* LED 1 (P0.17 on the board) */ #define TASK_LED 17 /* 2 (P0.18 on the board) */ #define CALLOUT_LED 18 /* LED 3 (P0.19 on the board) */ #define GPIO_LED 19 /* Button 1 (P0.13 on the board) */ #define BUTTON1_PIN 13 void init_tasks () /* Initialize OS callout for timer events. */ .... /* * Initialize and enable interrupts for the pin for button 1 and * configure the button with pull up resistor on the nrf52dk. */ hal_gpio_irq_init ( BUTTON1_PIN , my_gpio_irq , NULL , HAL_GPIO_TRIG_RISING , HAL_GPIO_PULL_UP ); hal_gpio_irq_enable ( BUTTON1_PIN ); /* Initialize the GPIO output pins. Value 1 is off for these LEDs. */ hal_gpio_init_out ( TASK_LED , 1 ); hal_gpio_init_out ( CALLOUT_LED , 1 ); hal_gpio_init_out ( GPIO_LED , 1 ); } Putting It All Together Here is the complete main.c source for your application. Build the application and load it on your board. The task LED (LED1) blinks at an interval of 250ms, the callout LED (LED2) blinks at an interval of 500ms, and the GPIO LED (LED3) toggles on or off each time you press Button 1. #include <os/os.h> #include <bsp/bsp.h> #include <hal/hal_gpio.h> #include <assert.h> #include <sysinit/sysinit.h> #define MY_TIMER_INTERRUPT_TASK_PRIO 4 #define MY_TIMER_INTERRUPT_TASK_STACK_SZ 512 #define GEN_TASK_PRIO 3 #define GEN_TASK_STACK_SZ 512 /* LED 1 (P0.17 on the board) */ #define TASK_LED 17 /* LED 2 (P0.18 on the board) */ #define CALLOUT_LED 18 /* LED 3 (P0.19 on the board) */ #define GPIO_LED 19 /* Button 1 (P0.13 on the board) */ #define BUTTON1_PIN 13 static void my_ev_cb ( struct os_event * ); static void my_timer_ev_cb ( struct os_event * ); static void my_interrupt_ev_cb ( struct os_event * ); static struct os_eventq my_timer_interrupt_eventq ; static os_stack_t my_timer_interrupt_task_stack [ MY_TIMER_INTERRUPT_TASK_STACK_SZ ]; static struct os_task my_timer_interrupt_task_str ; static os_stack_t gen_task_stack [ GEN_TASK_STACK_SZ ]; static struct os_task gen_task_str ; static struct os_event gen_task_ev = { . ev_cb = my_ev_cb , }; static struct os_event gpio_ev = { . ev_cb = my_interrupt_ev_cb , }; static struct os_callout my_callout ; /* * Task handler to generate an event to toggle the LED at pin TASK_LED. * The event is added to the Mynewt default event queue. */ static void gen_task ( void *arg ) { while ( 1 ) { os_time_delay ( OS_TICKS_PER_SEC / 4 ); os_eventq_put ( os_eventq_dflt_get (), &gen_task_ev ); } } /* * Event callback function for events generated by gen_task. It toggles the LED at pin TASK_LED. */ static void my_ev_cb ( struct os_event *ev ) { assert ( ev ); hal_gpio_toggle ( TASK_LED ); return ; } /* * Event callback function for timer events. It toggles the LED at pin CALLOUT_LED. */ static void my_timer_ev_cb ( struct os_event *ev ) { assert ( ev != NULL ); hal_gpio_toggle ( CALLOUT_LED ); os_callout_reset ( &my_callout , OS_TICKS_PER_SEC / 2 ); } /* * Event callback function for interrupt events. It toggles the LED at pin GPIO_LED. */ static void my_interrupt_ev_cb ( struct os_event *ev ) { assert ( ev != NULL ); hal_gpio_toggle ( GPIO_LED ); } static void my_gpio_irq ( void *arg ) { os_eventq_put ( &my_timer_interrupt_eventq , &gpio_ev ); } static void my_timer_interrupt_task ( void *arg ) { while ( 1 ) { os_eventq_run ( &my_timer_interrupt_eventq ); } } void init_tasks ( void ) { /* Create a task to generate events to toggle the LED at pin TASK_LED */ os_task_init ( &gen_task_str , \"gen_task\" , gen_task , NULL , GEN_TASK_PRIO , OS_WAIT_FOREVER , gen_task_stack , GEN_TASK_STACK_SZ ); /* Use a dedicate event queue for timer and interrupt events */ os_eventq_init ( &my_timer_interrupt_eventq ); /* * Create the task to process timer and interrupt events from the * my_timer_interrupt_eventq event queue. */ os_task_init ( &my_timer_interrupt_task_str , \"timer_interrupt_task\" , my_timer_interrupt_task , NULL , MY_TIMER_INTERRUPT_TASK_PRIO , OS_WAIT_FOREVER , my_timer_interrupt_task_stack , MY_TIMER_INTERRUPT_TASK_STACK_SZ ); /* * Initialize the callout for a timer event. * The my_timer_ev_cb callback function processes the timer event. */ os_callout_init ( &my_callout , &my_timer_interrupt_eventq , my_timer_ev_cb , NULL ); os_callout_reset ( &my_callout , OS_TICKS_PER_SEC ); /* * Initialize and enable interrupt for the pin for button 1 and * configure the button with pull up resistor on the nrf52dk. */ hal_gpio_irq_init ( BUTTON1_PIN , my_gpio_irq , NULL , HAL_GPIO_TRIG_RISING , HAL_GPIO_PULL_UP ); hal_gpio_irq_enable ( BUTTON1_PIN ); hal_gpio_init_out ( TASK_LED , 1 ); hal_gpio_init_out ( CALLOUT_LED , 1 ); hal_gpio_init_out ( GPIO_LED , 1 ); } int main ( int argc , char **argv ) { sysinit (); init_tasks (); while ( 1 ) { os_eventq_run ( os_eventq_dflt_get ()); } assert ( 0 ); }","title":"Events and Event Queues"},{"location":"os/tutorials/event_queue/#how-to-use-event-queues-to-manage-multiple-events","text":"","title":"How to Use Event Queues to Manage Multiple Events"},{"location":"os/tutorials/event_queue/#introduction","text":"The event queue mechanism allows you to serialize incoming events for your task. You can use it to get information about hardware interrupts, callout expirations, and messages from other tasks. The benefit of using events for inter-task communication is that it can reduce the number of resources that need to be shared and locked. The benefit of processing interrupts in a task context instead of the interrupt context is that other interrupts and high priority tasks are not blocked waiting for the interrupt handler to complete processing. A task can also access other OS facilities and sleep. This tutorial assumes that you have read about Event Queues , the Hardware Abstraction Layer , and OS Callouts in the OS User's Guide. This tutorial shows you how to create an application that uses events for: Inter-task communication OS callouts for timer expiration GPIO interrupts It also shows you how to: Use the Mynewt default event queue and application main task to process your events. Create a dedicated event queue and task for your events. To reduce an application's memory requirement, we recommend that you use the Mynewt default event queue if your application or package does not have real-time timing requirements.","title":"Introduction"},{"location":"os/tutorials/event_queue/#prerequisites","text":"Ensure that you have met the following prerequisites before continuing with this tutorial: Install the newt tool. Install the newtmgr tool. Have Internet connectivity to fetch remote Mynewt components. Install the compiler tools to support native compiling to build the project this tutorial creates. Have a cable to establish a serial USB connection between the board and the laptop.","title":"Prerequisites"},{"location":"os/tutorials/event_queue/#example-application","text":"In this example, you will write an application, for the Nordic nRF52 board, that uses events from three input sources to toggle three GPIO outputs and light up the LEDs. If you are using a different board, you will need to adjust the GPIO pin numbers in the code example. The application handles events from three sources on two event queues: Events generated by an application task at periodic intervals are added to the Mynewt default event queue. OS callouts for timer events are added to the my_timer_interrupt_eventq event queue. GPIO interrupt events are added to the my_timer_interrupt_eventq event queue.","title":"Example Application"},{"location":"os/tutorials/event_queue/#create-the-project","text":"Follow the instructions in the nRF52 tutorial to create a project.","title":"Create the Project"},{"location":"os/tutorials/event_queue/#create-the-application","text":"Create the pkg.yml file for the application: pkg.name: apps/eventq_example pkg.type: app pkg.deps: - kernel/os - hw/hal - sys/console/stub","title":"Create the Application"},{"location":"os/tutorials/event_queue/#application-task-generated-events","text":"The application creates a task that generates events, at periodic intervals, to toggle the LED at pin TASK_LED . The event is queued on the Mynewt default event queue and is processed in the context of the application main task. Declare and initialize the gen_task_ev event with the my_ev_cb() callback function to process the event: /* Callback function for application task event */ static void my_ev_cb ( struct os_event * ); /* Initialize the event with the callback function */ static struct os_event gen_task_ev = { . ev_cb = my_ev_cb , }; Implement the my_ev_cb() callback function to process a task generated event and toggle the LED at pin TASK_LED : /* LED 1 (P0.17 on the board) */ #define TASK_LED 17 /* * Event callback function for events generated by gen_task. It toggles * the LED at pin TASK_LED. */ static void my_ev_cb ( struct os_event *ev ) { assert ( ev ); hal_gpio_toggle ( TASK_LED ); return ; } Create a task that generates an event at periodic intervals and adds, using the os_eventq_put() function, the event to the Mynewt default event queue: #define GEN_TASK_PRIO 3 #define GEN_TASK_STACK_SZ 512 static os_stack_t gen_task_stack [ GEN_TASK_STACK_SZ ]; static struct os_task gen_task_str ; /* * Task handler to generate an event to toggle the LED at pin TASK_LED. * The event is added to the Mynewt default event queue. */ static void gen_task ( void *arg ) { while ( 1 ) { os_time_delay ( OS_TICKS_PER_SEC / 4 ); os_eventq_put ( os_eventq_dflt_get (), &gen_task_ev ); } } static void init_tasks ( void ) { /* Create a task to generate events to toggle the LED at pin TASK_LED */ os_task_init ( &gen_task_str , \"gen_task\" , gen_task , NULL , GEN_TASK_PRIO , OS_WAIT_FOREVER , gen_task_stack , GEN_TASK_STACK_SZ ); ... } Implement the application main() function to call the os_eventq_run() function to dequeue an event from the Mynewt default event queue and call the callback function to process the event. int main ( int argc , char **argv ) { sysinit (); init_tasks (); while ( 1 ) { os_eventq_run ( os_eventq_dflt_get ()); } assert ( 0 ); }","title":"Application Task Generated Events"},{"location":"os/tutorials/event_queue/#os-callout-timer-events","text":"Set up OS callout timer events. For this example, we use a dedicated event queue for timer events to show you how to create a dedicated event queue and a task to process the events. Implement the my_timer_ev_cb() callback function to process a timer event and toggle the LED at pin CALLOUT_LED : /* LED 2 (P0.18 on the board) */ #define CALLOUT_LED 18 /* The timer callout */ static struct os_callout my_callout ; /* * Event callback function for timer events. It toggles the LED at pin CALLOUT_LED. */ static void my_timer_ev_cb ( struct os_event *ev ) { assert ( ev != NULL ); hal_gpio_toggle ( CALLOUT_LED ); os_callout_reset ( &my_callout , OS_TICKS_PER_SEC / 2 ); } In the init_tasks() function, initialize the my_timer_interrupt_eventq event queue, create a task to process events from the queue, and initialize the OS callout for the timer: #define MY_TIMER_INTERRUPT_TASK_PRIO 4 #define MY_TIMER_INTERRUPT_TASK_STACK_SZ 512 static os_stack_t my_timer_interrupt_task_stack [ MY_TIMER_INTERRUPT_TASK_STACK_SZ ]; static struct os_task my_timer_interrupt_task_str ; static void init_tasks ( void ) { /* Use a dedicate event queue for timer and interrupt events */ os_eventq_init ( &my_timer_interrupt_eventq ); /* * Create the task to process timer and interrupt events from the * my_timer_interrupt_eventq event queue. */ os_task_init ( &my_timer_interrupt_task_str , \"timer_interrupt_task\" , my_timer_interrupt_task , NULL , MY_TIMER_INTERRUPT_TASK_PRIO , OS_WAIT_FOREVER , my_timer_interrupt_task_stack , MY_TIMER_INTERRUPT_TASK_STACK_SZ ); /* * Initialize the callout for a timer event. * The my_timer_ev_cb callback function processes the timer events. */ os_callout_init ( &my_callout , &my_timer_interrupt_eventq , my_timer_ev_cb , NULL ); os_callout_reset ( &my_callout , OS_TICKS_PER_SEC ); } Implement the my_timer_interrupt_task() task handler to dispatch events from the my_timer_interrupt_eventq event queue: static void my_timer_interrupt_task ( void *arg ) { while ( 1 ) { os_eventq_run ( &my_timer_interrupt_eventq ); } }","title":"OS Callout Timer Events"},{"location":"os/tutorials/event_queue/#interrupt-events","text":"The application toggles the LED each time button 1 on the board is pressed. The interrupt handler generates an event when the GPIO for button 1 (P0.13) changes state. The events are added to the my_timer_interrupt_eventq event queue, the same queue as the timer events. Declare and initialize the gpio_ev event with the my_interrupt_ev_cb() callback function to process the event: static struct os_event gpio_ev { . ev_cb = my_interrupt_ev_cb , }; Implement the my_interrupt_ev_cb() callback function to process an interrupt event and toggle the LED at pin GPIO_LED : /* LED 3 (P0.19 on the board) */ #define GPIO_LED 19 /* * Event callback function for interrupt events. It toggles the LED at pin GPIO_LED. */ static void my_interrupt_ev_cb ( struct os_event *ev ) { assert ( ev != NULL ); hal_gpio_toggle ( GPIO_LED ); } Implement the my_gpio_irq() handler to post an interrupt event to the my_timer_interrupt_eventq event queue: static void my_gpio_irq ( void *arg ) { os_eventq_put ( &my_timer_interrupt_eventq , &gpio_ev ); } In the init_tasks() function, add the code to set up and enable the GPIO input pin for the button and initialize the GPIO output pins for the LEDs: /* LED 1 (P0.17 on the board) */ #define TASK_LED 17 /* 2 (P0.18 on the board) */ #define CALLOUT_LED 18 /* LED 3 (P0.19 on the board) */ #define GPIO_LED 19 /* Button 1 (P0.13 on the board) */ #define BUTTON1_PIN 13 void init_tasks () /* Initialize OS callout for timer events. */ .... /* * Initialize and enable interrupts for the pin for button 1 and * configure the button with pull up resistor on the nrf52dk. */ hal_gpio_irq_init ( BUTTON1_PIN , my_gpio_irq , NULL , HAL_GPIO_TRIG_RISING , HAL_GPIO_PULL_UP ); hal_gpio_irq_enable ( BUTTON1_PIN ); /* Initialize the GPIO output pins. Value 1 is off for these LEDs. */ hal_gpio_init_out ( TASK_LED , 1 ); hal_gpio_init_out ( CALLOUT_LED , 1 ); hal_gpio_init_out ( GPIO_LED , 1 ); }","title":"Interrupt Events"},{"location":"os/tutorials/event_queue/#putting-it-all-together","text":"Here is the complete main.c source for your application. Build the application and load it on your board. The task LED (LED1) blinks at an interval of 250ms, the callout LED (LED2) blinks at an interval of 500ms, and the GPIO LED (LED3) toggles on or off each time you press Button 1. #include <os/os.h> #include <bsp/bsp.h> #include <hal/hal_gpio.h> #include <assert.h> #include <sysinit/sysinit.h> #define MY_TIMER_INTERRUPT_TASK_PRIO 4 #define MY_TIMER_INTERRUPT_TASK_STACK_SZ 512 #define GEN_TASK_PRIO 3 #define GEN_TASK_STACK_SZ 512 /* LED 1 (P0.17 on the board) */ #define TASK_LED 17 /* LED 2 (P0.18 on the board) */ #define CALLOUT_LED 18 /* LED 3 (P0.19 on the board) */ #define GPIO_LED 19 /* Button 1 (P0.13 on the board) */ #define BUTTON1_PIN 13 static void my_ev_cb ( struct os_event * ); static void my_timer_ev_cb ( struct os_event * ); static void my_interrupt_ev_cb ( struct os_event * ); static struct os_eventq my_timer_interrupt_eventq ; static os_stack_t my_timer_interrupt_task_stack [ MY_TIMER_INTERRUPT_TASK_STACK_SZ ]; static struct os_task my_timer_interrupt_task_str ; static os_stack_t gen_task_stack [ GEN_TASK_STACK_SZ ]; static struct os_task gen_task_str ; static struct os_event gen_task_ev = { . ev_cb = my_ev_cb , }; static struct os_event gpio_ev = { . ev_cb = my_interrupt_ev_cb , }; static struct os_callout my_callout ; /* * Task handler to generate an event to toggle the LED at pin TASK_LED. * The event is added to the Mynewt default event queue. */ static void gen_task ( void *arg ) { while ( 1 ) { os_time_delay ( OS_TICKS_PER_SEC / 4 ); os_eventq_put ( os_eventq_dflt_get (), &gen_task_ev ); } } /* * Event callback function for events generated by gen_task. It toggles the LED at pin TASK_LED. */ static void my_ev_cb ( struct os_event *ev ) { assert ( ev ); hal_gpio_toggle ( TASK_LED ); return ; } /* * Event callback function for timer events. It toggles the LED at pin CALLOUT_LED. */ static void my_timer_ev_cb ( struct os_event *ev ) { assert ( ev != NULL ); hal_gpio_toggle ( CALLOUT_LED ); os_callout_reset ( &my_callout , OS_TICKS_PER_SEC / 2 ); } /* * Event callback function for interrupt events. It toggles the LED at pin GPIO_LED. */ static void my_interrupt_ev_cb ( struct os_event *ev ) { assert ( ev != NULL ); hal_gpio_toggle ( GPIO_LED ); } static void my_gpio_irq ( void *arg ) { os_eventq_put ( &my_timer_interrupt_eventq , &gpio_ev ); } static void my_timer_interrupt_task ( void *arg ) { while ( 1 ) { os_eventq_run ( &my_timer_interrupt_eventq ); } } void init_tasks ( void ) { /* Create a task to generate events to toggle the LED at pin TASK_LED */ os_task_init ( &gen_task_str , \"gen_task\" , gen_task , NULL , GEN_TASK_PRIO , OS_WAIT_FOREVER , gen_task_stack , GEN_TASK_STACK_SZ ); /* Use a dedicate event queue for timer and interrupt events */ os_eventq_init ( &my_timer_interrupt_eventq ); /* * Create the task to process timer and interrupt events from the * my_timer_interrupt_eventq event queue. */ os_task_init ( &my_timer_interrupt_task_str , \"timer_interrupt_task\" , my_timer_interrupt_task , NULL , MY_TIMER_INTERRUPT_TASK_PRIO , OS_WAIT_FOREVER , my_timer_interrupt_task_stack , MY_TIMER_INTERRUPT_TASK_STACK_SZ ); /* * Initialize the callout for a timer event. * The my_timer_ev_cb callback function processes the timer event. */ os_callout_init ( &my_callout , &my_timer_interrupt_eventq , my_timer_ev_cb , NULL ); os_callout_reset ( &my_callout , OS_TICKS_PER_SEC ); /* * Initialize and enable interrupt for the pin for button 1 and * configure the button with pull up resistor on the nrf52dk. */ hal_gpio_irq_init ( BUTTON1_PIN , my_gpio_irq , NULL , HAL_GPIO_TRIG_RISING , HAL_GPIO_PULL_UP ); hal_gpio_irq_enable ( BUTTON1_PIN ); hal_gpio_init_out ( TASK_LED , 1 ); hal_gpio_init_out ( CALLOUT_LED , 1 ); hal_gpio_init_out ( GPIO_LED , 1 ); } int main ( int argc , char **argv ) { sysinit (); init_tasks (); while ( 1 ) { os_eventq_run ( os_eventq_dflt_get ()); } assert ( 0 ); }","title":"Putting It All Together"},{"location":"os/tutorials/ibeacon/","text":"BLE iBeacon iBeacon Protocol A beaconing device announces its presence to the world by broadcasting advertisements. The iBeacon protocol is built on top of the standard BLE advertisement specification. An iBeacon advertisement contains a single field: Manufacturer Specific Data ; this field contains the iBeacon-specific sub-fields. This page provides a good summary of the iBeacon sub-fields. Configuration Use the following function to configure your NimBLE device to send iBeacons: int ble_ibeacon_set_adv_data ( void *uuid128 , uint16_t major , uint16_t minor ) This function's parameters are documented below. Parameter Purpose UUID 128-bit UUID identifying the application Major version number First number in your app's version Minor version number Second number in your app's version Modify bleprph To demonstrate how the above function is used, we will now modify the bleprph example application to send iBeacons. For some background behind the bleprph app, we recommend you take a look at the bleprph project tutorial . If you plan on making these modifications yourself, it might be a good idea to copy bleprph to your local repository and work with the copy. In general, you should avoid changing a package that newt downloads, as you will lose your changes the next time you upgrade the package. bleprph sets its advertisement data and begins advertising as follows ( main.c ): static void bleprph_advertise ( void ) { struct ble_gap_adv_params adv_params ; struct ble_hs_adv_fields fields ; const char *name ; int rc ; /** * Set the advertisement data included in our advertisements: * o Flags (indicates advertisement type and other general info). * o Advertising tx power. * o Device name. * o 16-bit service UUIDs (alert notifications). */ memset ( &fields , 0 , sizeof fields ); /* Advertise two flags: * o Discoverability in forthcoming advertisement (general) * o BLE-only (BR/EDR unsupported). */ fields . flags = BLE_HS_ADV_F_DISC_GEN | BLE_HS_ADV_F_BREDR_UNSUP ; /* Indicate that the TX power level field should be included; have the * stack fill this value automatically. This is done by assiging the * special value BLE_HS_ADV_TX_PWR_LVL_AUTO. */ fields . tx_pwr_lvl_is_present = 1 ; fields . tx_pwr_lvl = BLE_HS_ADV_TX_PWR_LVL_AUTO ; name = ble_svc_gap_device_name (); fields . name = ( uint8_t * ) name ; fields . name_len = strlen ( name ); fields . name_is_complete = 1 ; fields . uuids16 = ( ble_uuid16_t []){ BLE_UUID16_INIT ( GATT_SVR_SVC_ALERT_UUID ) }; fields . num_uuids16 = 1 ; fields . uuids16_is_complete = 1 ; rc = ble_gap_adv_set_fields ( &fields ); if ( rc != 0 ) { BLEPRPH_LOG ( ERROR , \"error setting advertisement data; rc=%d\\n\" , rc ); return ; } /* Begin advertising. */ memset ( &adv_params , 0 , sizeof adv_params ); adv_params . conn_mode = BLE_GAP_CONN_MODE_UND ; adv_params . disc_mode = BLE_GAP_DISC_MODE_GEN ; rc = ble_gap_adv_start ( BLE_OWN_ADDR_PUBLIC , NULL , BLE_HS_FOREVER , &adv_params , bleprph_gap_event , NULL ); if ( rc != 0 ) { BLEPRPH_LOG ( ERROR , \"error enabling advertisement; rc=%d\\n\" , rc ); return ; } } The call to ble_gap_adv_set_fields() configures the device with normal (non-iBeacon) advertisements; the call to ble_gap_adv_start() tells the NimBLE stack to start broadcasting. We are now going to create an iBeacon app by making the following two changes: Call ble_ibeacon_set_adv_data() instead of ble_gap_adv_set_fields() . Modify the call to ble_gap_adv_start() such that the device is non-discoverable and non-connectable. static void bleprph_advertise ( void ) { struct ble_gap_adv_params adv_params ; uint8_t uuid128 [ 16 ]; int rc ; /* Arbitrarily set the UUID to a string of 0x11 bytes. */ memset ( uuid128 , 0x11 , sizeof uuid128 ); /* Major version=2; minor version=10. */ rc = ble_ibeacon_set_adv_data ( uuid128 , 2 , 10 ); if ( rc != 0 ) { BLEPRPH_LOG ( ERROR , \"error setting iBeacon advertisement data; rc=%d\\n\" , rc ); return ; } /* Begin advertising. */ memset ( &adv_params , 0 , sizeof adv_params ); adv_params . conn_mode = BLE_GAP_CONN_MODE_NON ; adv_params . disc_mode = BLE_GAP_DISC_MODE_NON ; rc = ble_gap_adv_start ( BLE_OWN_ADDR_PUBLIC , NULL , BLE_HS_FOREVER , &adv_params , bleprph_gap_event , NULL ); if ( rc != 0 ) { BLEPRPH_LOG ( ERROR , \"error enabling advertisement; rc=%d\\n\" , rc ); return ; } } Now when you run this app on your board, you should be able to see it with all your iBeacon-aware devices.","title":"BLE iBeacon"},{"location":"os/tutorials/ibeacon/#ble-ibeacon","text":"","title":"BLE iBeacon"},{"location":"os/tutorials/ibeacon/#ibeacon-protocol","text":"A beaconing device announces its presence to the world by broadcasting advertisements. The iBeacon protocol is built on top of the standard BLE advertisement specification. An iBeacon advertisement contains a single field: Manufacturer Specific Data ; this field contains the iBeacon-specific sub-fields. This page provides a good summary of the iBeacon sub-fields.","title":"iBeacon Protocol"},{"location":"os/tutorials/ibeacon/#configuration","text":"Use the following function to configure your NimBLE device to send iBeacons: int ble_ibeacon_set_adv_data ( void *uuid128 , uint16_t major , uint16_t minor ) This function's parameters are documented below. Parameter Purpose UUID 128-bit UUID identifying the application Major version number First number in your app's version Minor version number Second number in your app's version","title":"Configuration"},{"location":"os/tutorials/ibeacon/#modify-bleprph","text":"To demonstrate how the above function is used, we will now modify the bleprph example application to send iBeacons. For some background behind the bleprph app, we recommend you take a look at the bleprph project tutorial . If you plan on making these modifications yourself, it might be a good idea to copy bleprph to your local repository and work with the copy. In general, you should avoid changing a package that newt downloads, as you will lose your changes the next time you upgrade the package. bleprph sets its advertisement data and begins advertising as follows ( main.c ): static void bleprph_advertise ( void ) { struct ble_gap_adv_params adv_params ; struct ble_hs_adv_fields fields ; const char *name ; int rc ; /** * Set the advertisement data included in our advertisements: * o Flags (indicates advertisement type and other general info). * o Advertising tx power. * o Device name. * o 16-bit service UUIDs (alert notifications). */ memset ( &fields , 0 , sizeof fields ); /* Advertise two flags: * o Discoverability in forthcoming advertisement (general) * o BLE-only (BR/EDR unsupported). */ fields . flags = BLE_HS_ADV_F_DISC_GEN | BLE_HS_ADV_F_BREDR_UNSUP ; /* Indicate that the TX power level field should be included; have the * stack fill this value automatically. This is done by assiging the * special value BLE_HS_ADV_TX_PWR_LVL_AUTO. */ fields . tx_pwr_lvl_is_present = 1 ; fields . tx_pwr_lvl = BLE_HS_ADV_TX_PWR_LVL_AUTO ; name = ble_svc_gap_device_name (); fields . name = ( uint8_t * ) name ; fields . name_len = strlen ( name ); fields . name_is_complete = 1 ; fields . uuids16 = ( ble_uuid16_t []){ BLE_UUID16_INIT ( GATT_SVR_SVC_ALERT_UUID ) }; fields . num_uuids16 = 1 ; fields . uuids16_is_complete = 1 ; rc = ble_gap_adv_set_fields ( &fields ); if ( rc != 0 ) { BLEPRPH_LOG ( ERROR , \"error setting advertisement data; rc=%d\\n\" , rc ); return ; } /* Begin advertising. */ memset ( &adv_params , 0 , sizeof adv_params ); adv_params . conn_mode = BLE_GAP_CONN_MODE_UND ; adv_params . disc_mode = BLE_GAP_DISC_MODE_GEN ; rc = ble_gap_adv_start ( BLE_OWN_ADDR_PUBLIC , NULL , BLE_HS_FOREVER , &adv_params , bleprph_gap_event , NULL ); if ( rc != 0 ) { BLEPRPH_LOG ( ERROR , \"error enabling advertisement; rc=%d\\n\" , rc ); return ; } } The call to ble_gap_adv_set_fields() configures the device with normal (non-iBeacon) advertisements; the call to ble_gap_adv_start() tells the NimBLE stack to start broadcasting. We are now going to create an iBeacon app by making the following two changes: Call ble_ibeacon_set_adv_data() instead of ble_gap_adv_set_fields() . Modify the call to ble_gap_adv_start() such that the device is non-discoverable and non-connectable. static void bleprph_advertise ( void ) { struct ble_gap_adv_params adv_params ; uint8_t uuid128 [ 16 ]; int rc ; /* Arbitrarily set the UUID to a string of 0x11 bytes. */ memset ( uuid128 , 0x11 , sizeof uuid128 ); /* Major version=2; minor version=10. */ rc = ble_ibeacon_set_adv_data ( uuid128 , 2 , 10 ); if ( rc != 0 ) { BLEPRPH_LOG ( ERROR , \"error setting iBeacon advertisement data; rc=%d\\n\" , rc ); return ; } /* Begin advertising. */ memset ( &adv_params , 0 , sizeof adv_params ); adv_params . conn_mode = BLE_GAP_CONN_MODE_NON ; adv_params . disc_mode = BLE_GAP_DISC_MODE_NON ; rc = ble_gap_adv_start ( BLE_OWN_ADDR_PUBLIC , NULL , BLE_HS_FOREVER , &adv_params , bleprph_gap_event , NULL ); if ( rc != 0 ) { BLEPRPH_LOG ( ERROR , \"error enabling advertisement; rc=%d\\n\" , rc ); return ; } } Now when you run this app on your board, you should be able to see it with all your iBeacon-aware devices.","title":"Modify bleprph"},{"location":"os/tutorials/nRF52/","text":"Blinky, your \"Hello World!\", on nRF52 This tutorial shows you how to create, build, and run the Blinky application on the nRF52 board. Note that there are several versions of the nRF52 in the market. The boards tested with this tutorial are listed under \"Prerequisites\". Prerequisites Meet the prerequisites listed in Project Blinky . Have a nRF52 Development Kit (one of the following) Dev Kit from Nordic - PCA 10040 Eval Kit from Rigado - BMD-300-EVAL-ES Install the Segger JLINK Software and documentation pack . This tutorial uses the Nordic nRF52-DK board. Create a Project Create a new project if you do not have an existing one. You can skip this step and proceed to create the targets if you already have a project created. Run the following commands to create a new project: $ mkdir ~/dev $ cd ~/dev $ newt new myproj Downloading project skeleton from apache/incubator-mynewt-blinky... Installing skeleton in myproj... Project myproj successfully created. $ cd myproj $ newt install apache-mynewt-core $ Create the Targets Create two targets for the nRF52-DK board - one for the bootloader and one for the Blinky application. Run the following newt target commands, from your project directory, to create a bootloader target. We name the target nrf52_boot : Note: This tutorial uses the Nordic nRF52-DK board. You must specify the correct bsp for the board you are using. For the Nordic Dev Kit choose @apache-mynewt-core/hw/bsp/nrf52dk instead (in the highlighted lines) For the Rigado Eval Kit choose @apache-mynewt-core/hw/bsp/bmd300eval instead (in the highlighted lines) $ newt target create nrf52_boot $ newt target set nrf52_boot app=@apache-mynewt-core/apps/boot $ newt target set nrf52_boot bsp=@apache-mynewt-core/hw/bsp/nrf52dk $ newt target set nrf52_boot build_profile=optimized Run the following newt target commands to create a target for the Blinky application. We name the target nrf52_blinky . $ newt target create nrf52_blinky $ newt target set nrf52_blinky app=apps/blinky $ newt target set nrf52_blinky bsp=@apache-mynewt-core/hw/bsp/nrf52dk $ newt target set nrf52_blinky build_profile=debug You can run the newt target show command to verify the target settings: $ newt target show targets/nrf52_blinky app=apps/blinky bsp=@apache-mynewt-core/hw/bsp/nrf52dk build_profile=debug targets/nrf52_boot app=@apache-mynewt-core/apps/boot bsp=@apache-mynewt-core/hw/bsp/nrf52dk build_profile=optimized Build the Target Executables Run the newt build nrf52_boot command to build the bootloader: $ newt build nrf52_boot Building target targets/nrf52_boot Compiling repos/apache-mynewt-core/boot/bootutil/src/image_ec256.c Compiling repos/apache-mynewt-core/boot/bootutil/src/image_ec.c Compiling repos/apache-mynewt-core/boot/bootutil/src/image_rsa.c Compiling repos/apache-mynewt-core/crypto/mbedtls/src/aes.c Compiling repos/apache-mynewt-core/boot/bootutil/src/loader.c Compiling repos/apache-mynewt-core/boot/bootutil/src/image_validate.c Compiling repos/apache-mynewt-core/boot/bootutil/src/bootutil_misc.c Compiling repos/apache-mynewt-core/apps/boot/src/boot.c ... Archiving sys_mfg.a Archiving sys_sysinit.a Archiving util_mem.a Linking ~/dev/myproj/bin/targets/nrf52_boot/app/apps/boot/boot.elf Target successfully built: targets/nrf52_boot Run the newt build nrf52_blinky command to build the Blinky application: $ newt build nrf52_blinky Building target targets/nrf52_blinky Assembling repos/apache-mynewt-core/hw/bsp/nrf52dk/src/arch/cortex_m4/gcc_startup_nrf52_split.s Compiling repos/apache-mynewt-core/hw/bsp/nrf52dk/src/sbrk.c Compiling repos/apache-mynewt-core/hw/cmsis-core/src/cmsis_nvic.c Compiling repos/apache-mynewt-core/hw/drivers/uart/uart_hal/src/uart_hal.c Assembling repos/apache-mynewt-core/hw/bsp/nrf52dk/src/arch/cortex_m4/gcc_startup_nrf52.s Compiling apps/blinky/src/main.c ... Archiving sys_mfg.a Archiving sys_sysinit.a Archiving util_mem.a Linking ~/dev/myproj/bin/targets/nrf52_blinky/app/apps/blinky/blinky.elf Target successfully built: targets/nrf52_blinky Sign and Create the Blinky Application Image Run the newt create-image nrf52_blinky 1.0.0 command to create and sign the application image. You may assign an arbitrary version (e.g. 1.0.0) to the image. $ newt create-image nrf52_blinky 1.0.0 App image succesfully generated: ~/dev/myproj/bin/targets/nrf52_blinky/app/apps/blinky/blinky.img Connect to the Board Connect a micro-USB cable from your computer to the micro-USB port on the nRF52-DK board. Turn the power on the board to ON. You should see the green LED light up on the board. Load the Bootloader and the Blinky Application Image Run the newt load nrf52_boot command to load the bootloader onto the board: $ newt load nrf52_boot Loading bootloader $ Run the newt load nrf52_blinky command to load the Blinky application image onto the board. $ newt load nrf52_blinky Loading app image into slot 1 You should see the LED1 on the board blink! Note: If the LED does not blink, try resetting your board. If you want to erase the flash and load the image again, you can run JLinkExe to issue an erase command. Note: On Windows: Run the jlink command with the same arguments from a Windows Command Prompt terminal. $ JLinkExe -device nRF52 -speed 4000 -if SWD SEGGER J-Link Commander V5.12c (Compiled Apr 21 2016 16:05:51) DLL version V5.12c, compiled Apr 21 2016 16:05:45 Connecting to J-Link via USB...O.K. Firmware: J-Link OB-SAM3U128-V2-NordicSemi compiled Mar 15 2016 18:03:17 Hardware version: V1.00 S/N: 682863966 VTref = 3.300V Type \"connect\" to establish a target connection, '?' for help J-Link>erase Cortex-M4 identified. Erasing device (0;?i?)... Comparing flash [100%] Done. Erasing flash [100%] Done. Verifying flash [100%] Done. J-Link: Flash download: Total time needed: 0.363s (Prepare: 0.093s, Compare: 0.000s, Erase: 0.262s, Program: 0.000s, Verify: 0.000s, Restore: 0.008s) Erasing done. J-Link>exit $","title":"Blinky on nRF52"},{"location":"os/tutorials/nRF52/#blinky-your-hello-world-on-nrf52","text":"This tutorial shows you how to create, build, and run the Blinky application on the nRF52 board. Note that there are several versions of the nRF52 in the market. The boards tested with this tutorial are listed under \"Prerequisites\".","title":"Blinky, your \"Hello World!\", on nRF52"},{"location":"os/tutorials/nRF52/#prerequisites","text":"Meet the prerequisites listed in Project Blinky . Have a nRF52 Development Kit (one of the following) Dev Kit from Nordic - PCA 10040 Eval Kit from Rigado - BMD-300-EVAL-ES Install the Segger JLINK Software and documentation pack . This tutorial uses the Nordic nRF52-DK board.","title":"Prerequisites"},{"location":"os/tutorials/nRF52/#create-a-project","text":"Create a new project if you do not have an existing one. You can skip this step and proceed to create the targets if you already have a project created. Run the following commands to create a new project: $ mkdir ~/dev $ cd ~/dev $ newt new myproj Downloading project skeleton from apache/incubator-mynewt-blinky... Installing skeleton in myproj... Project myproj successfully created. $ cd myproj $ newt install apache-mynewt-core $","title":"Create a Project"},{"location":"os/tutorials/nRF52/#create-the-targets","text":"Create two targets for the nRF52-DK board - one for the bootloader and one for the Blinky application. Run the following newt target commands, from your project directory, to create a bootloader target. We name the target nrf52_boot : Note: This tutorial uses the Nordic nRF52-DK board. You must specify the correct bsp for the board you are using. For the Nordic Dev Kit choose @apache-mynewt-core/hw/bsp/nrf52dk instead (in the highlighted lines) For the Rigado Eval Kit choose @apache-mynewt-core/hw/bsp/bmd300eval instead (in the highlighted lines) $ newt target create nrf52_boot $ newt target set nrf52_boot app=@apache-mynewt-core/apps/boot $ newt target set nrf52_boot bsp=@apache-mynewt-core/hw/bsp/nrf52dk $ newt target set nrf52_boot build_profile=optimized Run the following newt target commands to create a target for the Blinky application. We name the target nrf52_blinky . $ newt target create nrf52_blinky $ newt target set nrf52_blinky app=apps/blinky $ newt target set nrf52_blinky bsp=@apache-mynewt-core/hw/bsp/nrf52dk $ newt target set nrf52_blinky build_profile=debug You can run the newt target show command to verify the target settings: $ newt target show targets/nrf52_blinky app=apps/blinky bsp=@apache-mynewt-core/hw/bsp/nrf52dk build_profile=debug targets/nrf52_boot app=@apache-mynewt-core/apps/boot bsp=@apache-mynewt-core/hw/bsp/nrf52dk build_profile=optimized","title":"Create the Targets"},{"location":"os/tutorials/nRF52/#build-the-target-executables","text":"Run the newt build nrf52_boot command to build the bootloader: $ newt build nrf52_boot Building target targets/nrf52_boot Compiling repos/apache-mynewt-core/boot/bootutil/src/image_ec256.c Compiling repos/apache-mynewt-core/boot/bootutil/src/image_ec.c Compiling repos/apache-mynewt-core/boot/bootutil/src/image_rsa.c Compiling repos/apache-mynewt-core/crypto/mbedtls/src/aes.c Compiling repos/apache-mynewt-core/boot/bootutil/src/loader.c Compiling repos/apache-mynewt-core/boot/bootutil/src/image_validate.c Compiling repos/apache-mynewt-core/boot/bootutil/src/bootutil_misc.c Compiling repos/apache-mynewt-core/apps/boot/src/boot.c ... Archiving sys_mfg.a Archiving sys_sysinit.a Archiving util_mem.a Linking ~/dev/myproj/bin/targets/nrf52_boot/app/apps/boot/boot.elf Target successfully built: targets/nrf52_boot Run the newt build nrf52_blinky command to build the Blinky application: $ newt build nrf52_blinky Building target targets/nrf52_blinky Assembling repos/apache-mynewt-core/hw/bsp/nrf52dk/src/arch/cortex_m4/gcc_startup_nrf52_split.s Compiling repos/apache-mynewt-core/hw/bsp/nrf52dk/src/sbrk.c Compiling repos/apache-mynewt-core/hw/cmsis-core/src/cmsis_nvic.c Compiling repos/apache-mynewt-core/hw/drivers/uart/uart_hal/src/uart_hal.c Assembling repos/apache-mynewt-core/hw/bsp/nrf52dk/src/arch/cortex_m4/gcc_startup_nrf52.s Compiling apps/blinky/src/main.c ... Archiving sys_mfg.a Archiving sys_sysinit.a Archiving util_mem.a Linking ~/dev/myproj/bin/targets/nrf52_blinky/app/apps/blinky/blinky.elf Target successfully built: targets/nrf52_blinky","title":"Build the Target Executables"},{"location":"os/tutorials/nRF52/#sign-and-create-the-blinky-application-image","text":"Run the newt create-image nrf52_blinky 1.0.0 command to create and sign the application image. You may assign an arbitrary version (e.g. 1.0.0) to the image. $ newt create-image nrf52_blinky 1.0.0 App image succesfully generated: ~/dev/myproj/bin/targets/nrf52_blinky/app/apps/blinky/blinky.img","title":"Sign and Create the Blinky Application Image"},{"location":"os/tutorials/nRF52/#connect-to-the-board","text":"Connect a micro-USB cable from your computer to the micro-USB port on the nRF52-DK board. Turn the power on the board to ON. You should see the green LED light up on the board.","title":"Connect to the Board"},{"location":"os/tutorials/nRF52/#load-the-bootloader-and-the-blinky-application-image","text":"Run the newt load nrf52_boot command to load the bootloader onto the board: $ newt load nrf52_boot Loading bootloader $ Run the newt load nrf52_blinky command to load the Blinky application image onto the board. $ newt load nrf52_blinky Loading app image into slot 1 You should see the LED1 on the board blink! Note: If the LED does not blink, try resetting your board. If you want to erase the flash and load the image again, you can run JLinkExe to issue an erase command. Note: On Windows: Run the jlink command with the same arguments from a Windows Command Prompt terminal. $ JLinkExe -device nRF52 -speed 4000 -if SWD SEGGER J-Link Commander V5.12c (Compiled Apr 21 2016 16:05:51) DLL version V5.12c, compiled Apr 21 2016 16:05:45 Connecting to J-Link via USB...O.K. Firmware: J-Link OB-SAM3U128-V2-NordicSemi compiled Mar 15 2016 18:03:17 Hardware version: V1.00 S/N: 682863966 VTref = 3.300V Type \"connect\" to establish a target connection, '?' for help J-Link>erase Cortex-M4 identified. Erasing device (0;?i?)... Comparing flash [100%] Done. Erasing flash [100%] Done. Verifying flash [100%] Done. J-Link: Flash download: Total time needed: 0.363s (Prepare: 0.093s, Compare: 0.000s, Erase: 0.262s, Program: 0.000s, Verify: 0.000s, Restore: 0.008s) Erasing done. J-Link>exit $","title":"Load the Bootloader and the Blinky Application Image"},{"location":"os/tutorials/nrf52_adc/","text":"Adding an Analog Sensor on nRF52 Objective We will be adding an analog sensor to the NRF52DK development board and using the Analog to Digital Converter (ADC) to read the values from the sensor. It's also using Bluetooth to allow you to connect to the app and read the value of the sensor. Please see the following section for the required hardware in order to complete this tutorial. Hardware needed nRF52 Development Kit (one of the following) Dev Kit from Nordic - PCA 10040 Eval Kit from Rigado - BMD-300-EVAL-ES eTape Liquid Sensor -- buy from Adafruit Laptop running Mac OS It is assumed you have already installed newt tool. It is assumed you already installed native tools as described here Create a project. Create a new project to hold your work. For a deeper understanding, you can read about project creation in Get Started -- Creating Your First Project or just follow the commands below. $ mkdir ~/dev $ cd ~/dev $ newt new myadc Downloading project skeleton from apache/incubator-mynewt-blinky... Installing skeleton in myadc... Project myadc successfully created. $ cd myadc Add Additional Repositories The board-specific libraries for the NRF52dk board are in an external repository at present, so you'll need to include that remote repository and install it as well. If you're not familiar with using repositories, see the section on repositories before continuing. Or just copy and paste the following. In your project.yml file, add mynewt_nordic to the project.repositories section, and then add the proper repository definition. When you're done, your project.yml file should look like this: project.name: \"my_project\" project.repositories: - apache-mynewt-core - mynewt_nordic # Use github's distribution mechanism for core ASF libraries. # This provides mirroring automatically for us. # repository.apache-mynewt-core: type: github vers: 1-latest user: apache repo: incubator-mynewt-core repository.mynewt_nordic: type: github vers: 1-latest user: runtimeco repo: mynewt_nordic Install Everything Now that you have defined the needed repositories, it's time to install everything so that you can get started. $ newt install -v apache-mynewt-core Downloading repository description for apache-mynewt-core... success! ... apache-mynewt-core successfully installed version 0.9.0-none ... mynewt_nordic Downloading repository description for mynewt_nordic... success! ... mynewt_nordic successfully installed version 0.9.9-none Create the targets Create two targets - one for the bootloader and one for the nrf52 board. Note: The correct bsp must be chosen for the board you are using. For the Nordic Dev Kit choose @apache-mynewt-core/hw/bsp/nrf52dk instead (in the highlighted lines) For the Rigado Eval Kit choose @apache-mynewt-core/hw/bsp/bmd300eval instead (in the highlighted lines) For the app itself we're going to extend the bleprph app so that we get the Bluetooth communications built in, so the first thing we'll need to do is copy that app into our own app directory: $ mkdir -p apps/nrf52_adc $ cp -Rp repos/apache-mynewt-core/apps/bleprph/* apps/nrf52_adc Next, you'll modify the pkg.yml file for your app. Note the change in pkg.name and pkg.description . Also make sure that you specify the full path of all the packages with the prefix @apache-mynewt-core/ as shown in the third highlighted line. $ cat apps/nrf52_adc/pkg.yml ... pkg.name: apps/nrf52_adc pkg.type: app pkg.description: Simple BLE peripheral application for ADC Sensors. pkg.author: \"Apache Mynewt <dev@mynewt.incubator.apache.org>\" pkg.homepage: \"http://mynewt.apache.org/\" pkg.keywords: pkg.deps: - \"@apache-mynewt-core/boot/split\" - \"@apache-mynewt-core/kernel/os\" - \"@apache-mynewt-core/mgmt/imgmgr\" - \"@apache-mynewt-core/mgmt/newtmgr\" - \"@apache-mynewt-core/mgmt/newtmgr/transport/ble\" - \"@apache-mynewt-core/net/nimble/controller\" - \"@apache-mynewt-core/net/nimble/host\" - \"@apache-mynewt-core/net/nimble/host/services/ans\" - \"@apache-mynewt-core/net/nimble/host/services/gap\" - \"@apache-mynewt-core/net/nimble/host/services/gatt\" - \"@apache-mynewt-core/net/nimble/host/store/ram\" - \"@apache-mynewt-core/net/nimble/transport/ram\" - \"@apache-mynewt-core/sys/console/full\" - \"@apache-mynewt-core/sys/log/full\" - \"@apache-mynewt-core/sys/stats/full\" - \"@apache-mynewt-core/sys/sysinit\" - \"@apache-mynewt-core/sys/id\" Great! We have our very own app so let's make sure we have all of our targets set correctly: $ newt target create nrf52_adc $ newt target set nrf52_adc app=apps/nrf52_adc Target targets/nrf52_adc successfully set target.app to apps/nrf52_adc $ newt target set nrf52_adc bsp=@apache-mynewt-core/hw/bsp/nrf52dk $ newt target set nrf52_adc build_profile=debug $ newt target create nrf52_boot $ newt target set nrf52_boot app=@apache-mynewt-core/apps/boot $ newt target set nrf52_boot bsp=@apache-mynewt-core/hw/bsp/nrf52dk $ newt target set nrf52_boot build_profile=optimized $ newt target show targets/nrf52_adc app=apps/nrf52_adc bsp=@apache-mynewt-core/hw/bsp/nrf52dk build_profile=debug targets/nrf52_boot app=@apache-mynewt-core/apps/boot bsp=@apache-mynewt-core/hw/bsp/nrf52dk build_profile=optimized Note: If you've already built and installed a bootloader for your NRF52dk then you do not need to create a target for it here, or build and load it as below. Build the target executables $ newt build nrf52_boot ... Compiling boot.c Archiving boot.a Linking boot.elf App successfully built: ~/dev/myadc/bin/nrf52_boot/apps/boot/boot.elf $ newt build nrf52_adc ... Compiling main.c Archiving nrf52_adc.a Linking nrf52_adc.elf App successfully built: ~/dev/myadc/bin/nrf52_adc/apps/nrf52_adc/nrf52_adc.elf Sign and create the nrf52_adc application image You must sign and version your application image to download it using newt to the board. Use the newt create-image command to perform this action. You may assign an arbitrary version (e.g. 1.0.0) to the image. $ newt create-image nrf52_adc 1.0.0 App image successfully generated: ~/dev/myadc/bin/nrf52_adc/apps/nrf52_adc/nrf52_adc.img Build manifest: ~/dev/myadc/bin/nrf52_adc/apps/nrf52_adc/manifest.json Connect the board Connect the evaluation board via micro-USB to your PC via USB cable. Download to the target Download the bootloader first and then the nrf52_adc executable to the target platform. Don't forget to reset the board if you don't see the LED blinking right away! $ newt load nrf52_boot $ newt load nrf52_adc Note: If you want to erase the flash and load the image again, you can use JLinkExe to issue an erase command. $ JLinkExe -device nRF52 -speed 4000 -if SWD SEGGER J-Link Commander V5.12c (Compiled Apr 21 2016 16:05:51) DLL version V5.12c, compiled Apr 21 2016 16:05:45 Connecting to J-Link via USB...O.K. Firmware: J-Link OB-SAM3U128-V2-NordicSemi compiled Mar 15 2016 18:03:17 Hardware version: V1.00 S/N: 682863966 VTref = 3.300V Type \"connect\" to establish a target connection, '?' for help J-Link>erase Cortex-M4 identified. Erasing device (0;?i?)... Comparing flash [100%] Done. Erasing flash [100%] Done. Verifying flash [100%] Done. J-Link: Flash download: Total time needed: 0.363s (Prepare: 0.093s, Compare: 0.000s, Erase: 0.262s, Program: 0.000s, Verify: 0.000s, Restore: 0.008s) Erasing done. J-Link>exit $ So you have a BLE app, but really all you've done is change the name of the bleprph app to nrf52_adc and load that. Not all that impressive, and it certainly won't read an Analog Sensor right now. So let's do that next. In order to read an ADC sensor, and since the ADC package is in an external, licensed, repository, we'll create a driver for it here in our app that will leverage the existing driver in the external repository. It adds another layer of indirection, but it will also give us a look at building our own driver, so we'll do it this way. Building a Driver The first thing to do is to create the directory structure for your driver: [user@IsMyLaptop:~/src/air_quality]$ mkdir -p libs/my_drivers/myadc/include/myadc [user@IsMyLaptop:~/src/air_quality]$ mkdir -p libs/my_drivers/myadc/src Now you can add the files you need. You'll need a pkg.yml to describe the driver, and then header stub followed by source stub. [user@IsMyLaptop:~/src/air_quality]$ cat libs/my_drivers/myadc/pkg.yml # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you 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. # pkg . name: libs/my_drivers/myadc pkg . deps: - \"@apache-mynewt-core/hw/hal\" - \"@mynewt_nordic/hw/drivers/adc/adc_nrf52\" First, let's create the required header file myadc.h in the includes directory i.e. libs/my_drivers/myadc/include/myadc/myadc.h . It's a pretty straightforward header file, since we only need to do 2 things: Initialize the ADC device Read ADC Values #ifndef _NRF52_ADC_H_ #define _NRF52_ADC_H_ void * adc_init ( void ); int adc_read ( void *buffer , int buffer_len ); #endif /* _NRF52_ADC_H_ */ Next we'll need a corresponding source file myadc.c in the src directory. This is where we'll implement the specifics of the driver: #include <assert.h> #include <os/os.h> /* ADC */ #include \"myadc/myadc.h\" #include \"nrf.h\" #include \"app_util_platform.h\" #include \"app_error.h\" #include <adc/adc.h> #include <adc_nrf52/adc_nrf52.h> #include \"nrf_drv_saadc.h\" #define ADC_NUMBER_SAMPLES (2) #define ADC_NUMBER_CHANNELS (1) nrf_drv_saadc_config_t adc_config = NRF_DRV_SAADC_DEFAULT_CONFIG ; struct adc_dev *adc ; uint8_t *sample_buffer1 ; uint8_t *sample_buffer2 ; static struct adc_dev os_bsp_adc0 ; static nrf_drv_saadc_config_t os_bsp_adc0_config = { . resolution = MYNEWT_VAL ( ADC_0_RESOLUTION ), . oversample = MYNEWT_VAL ( ADC_0_OVERSAMPLE ), . interrupt_priority = MYNEWT_VAL ( ADC_0_INTERRUPT_PRIORITY ), }; void * adc_init ( void ) { int rc = 0 ; rc = os_dev_create (( struct os_dev * ) &os_bsp_adc0 , \"adc0\" , OS_DEV_INIT_KERNEL , OS_DEV_INIT_PRIO_DEFAULT , nrf52_adc_dev_init , &os_bsp_adc0_config ); assert ( rc == 0 ); nrf_saadc_channel_config_t cc = NRF_DRV_SAADC_DEFAULT_CHANNEL_CONFIG_SE ( NRF_SAADC_INPUT_AIN1 ); cc . gain = NRF_SAADC_GAIN1_6 ; cc . reference = NRF_SAADC_REFERENCE_INTERNAL ; adc = ( struct adc_dev * ) os_dev_open ( \"adc0\" , 0 , &adc_config ); assert ( adc != NULL ); adc_chan_config ( adc , 0 , &cc ); sample_buffer1 = malloc ( adc_buf_size ( adc , ADC_NUMBER_CHANNELS , ADC_NUMBER_SAMPLES )); sample_buffer2 = malloc ( adc_buf_size ( adc , ADC_NUMBER_CHANNELS , ADC_NUMBER_SAMPLES )); memset ( sample_buffer1 , 0 , adc_buf_size ( adc , ADC_NUMBER_CHANNELS , ADC_NUMBER_SAMPLES )); memset ( sample_buffer2 , 0 , adc_buf_size ( adc , ADC_NUMBER_CHANNELS , ADC_NUMBER_SAMPLES )); adc_buf_set ( adc , sample_buffer1 , sample_buffer2 , adc_buf_size ( adc , ADC_NUMBER_CHANNELS , ADC_NUMBER_SAMPLES )); return adc ; } int adc_read ( void *buffer , int buffer_len ) { int i ; int adc_result ; int my_result_mv = 0 ; int rc ; for ( i = 0 ; i < ADC_NUMBER_SAMPLES ; i++ ) { rc = adc_buf_read ( adc , buffer , buffer_len , i , &adc_result ); if ( rc != 0 ) { goto err ; } my_result_mv = adc_result_mv ( adc , 0 , adc_result ); } adc_buf_release ( adc , buffer , buffer_len ); return my_result_mv ; err : return ( rc ); } There's a lot going on in here, so let's walk through it step by step. First, we define a default configuration, with the resolution, oversample and interrupt priority. You'll see that these are MYNEWT_VAL values, which means that we'll define them shortly in a syscfg.yml file to be passed to the compiler at build time. static struct adc_dev os_bsp_adc0 ; static nrf_drv_saadc_config_t os_bsp_adc0_config = { . resolution = MYNEWT_VAL ( ADC_0_RESOLUTION ), . oversample = MYNEWT_VAL ( ADC_0_OVERSAMPLE ), . interrupt_priority = MYNEWT_VAL ( ADC_0_INTERRUPT_PRIORITY ), }; Next, in adc_init() , we need to tell the OS to create the device. void * adc_init ( void ) { int rc = 0 ; rc = os_dev_create (( struct os_dev * ) &os_bsp_adc0 , \"adc0\" , OS_DEV_INIT_KERNEL , OS_DEV_INIT_PRIO_DEFAULT , nrf52_adc_dev_init , &os_bsp_adc0_config ); assert ( rc == 0 ); nrf_saadc_channel_config_t cc = NRF_DRV_SAADC_DEFAULT_CHANNEL_CONFIG_SE ( NRF_SAADC_INPUT_AIN1 ); cc . gain = NRF_SAADC_GAIN1_6 ; cc . reference = NRF_SAADC_REFERENCE_INTERNAL ; adc = ( struct adc_dev * ) os_dev_open ( \"adc0\" , 0 , &adc_config ); assert ( adc != NULL ); adc_chan_config ( adc , 0 , &cc ); sample_buffer1 = malloc ( adc_buf_size ( adc , ADC_NUMBER_CHANNELS , ADC_NUMBER_SAMPLES )); sample_buffer2 = malloc ( adc_buf_size ( adc , ADC_NUMBER_CHANNELS , ADC_NUMBER_SAMPLES )); memset ( sample_buffer1 , 0 , adc_buf_size ( adc , ADC_NUMBER_CHANNELS , ADC_NUMBER_SAMPLES )); memset ( sample_buffer2 , 0 , adc_buf_size ( adc , ADC_NUMBER_CHANNELS , ADC_NUMBER_SAMPLES )); adc_buf_set ( adc , sample_buffer1 , sample_buffer2 , adc_buf_size ( adc , ADC_NUMBER_CHANNELS , ADC_NUMBER_SAMPLES )); return adc ; } A few things need to be said about this part, as it is the most confusing. First, we're using a default configuration for the ADC Channel via the NRF_DRV_SAADC_DEFAULT_CHANNEL_CONFIG_SE macro. The important part here is that we're actually using AIN1 . I know what you're thinking, \"But we want ADC-0!\" and that's true. The board is actually labelled 'A0, A1, A2' etc., and the actual pin numbers are also listed on the board, which seems handy. At first. But it gets messy very quickly. If you try to use AIN0, and then go poke around in the registers while this is running, (gdb) p/x {NRF_SAADC_Type}0x40007000 ... CH = {{ PSELP = 0x1, PSELN = 0x0, CONFIG = 0x20000, LIMIT = 0x7fff8000 }, You'll see that the pin for channel 0 is set to 1, which corresponds to AIN0, but that's NOT the same as A0 -- pin P0.03, the one we're using. For that, you use AIN1, which would set the pin value to 2. Messy. Someone, somewhere, thought this made sense. The only other thing to note here is that we're using the internal reference voltage, rather than setting our own. There's nothing wrong with that, but since we are, we'll have to crank up the gain a bit by using NRF_SAADC_GAIN1_6 . Then, in adc_read() we will take readings, convert the raw readings to a millivolt equivalent, and return the result. int adc_read ( void *buffer , int buffer_len ) { int i ; int adc_result ; int my_result_mv = 0 ; int rc ; for ( i = 0 ; i < ADC_NUMBER_SAMPLES ; i++ ) { rc = adc_buf_read ( adc , buffer , buffer_len , i , &adc_result ); if ( rc != 0 ) { goto err ; } my_result_mv = adc_result_mv ( adc , 0 , adc_result ); } adc_buf_release ( adc , buffer , buffer_len ); return my_result_mv ; err : return ( rc ); } Finally, we'll need some settings for our driver, as mentioned earlier. In the myadc directory you'll need to add a syscfg.yml file: # Package: libs/my_driver/myadc syscfg.defs: ADC_0: description: 'TBD' value: 1 ADC_0_RESOLUTION: description: 'TBD' value: 'SAADC_CONFIG_RESOLUTION' ADC_0_OVERSAMPLE: description: 'TBD' value: 'SAADC_CONFIG_OVERSAMPLE' ADC_0_INTERRUPT_PRIORITY: description: 'TBD' value: 'SAADC_CONFIG_IRQ_PRIORITY' Once that's all done, you should have a working ADC Driver for your NRF52DK board. The last step in getting the driver set up is to include it in the package dependency defined by pkg.deps in the pkg.yml file of your app. Add it in apps/nrf52_adc/pkg.yml as shown by the highlighted line below. # Licensed to the Apache Software Foundation (ASF) under one # <snip> pkg.name: apps/nrf52_adc pkg.type: app pkg.description: Simple BLE peripheral application for ADC sensor. pkg.author: \"Apache Mynewt <dev@mynewt.incubator.apache.org>\" pkg.homepage: \"http://mynewt.apache.org/\" pkg.keywords: pkg.deps: - \"@apache-mynewt-core/boot/split\" - \"@apache-mynewt-core/kernel/os\" - \"@apache-mynewt-core/mgmt/imgmgr\" - \"@apache-mynewt-core/mgmt/newtmgr\" - \"@apache-mynewt-core/mgmt/newtmgr/transport/ble\" - \"@apache-mynewt-core/net/nimble/controller\" - \"@apache-mynewt-core/net/nimble/host\" - \"@apache-mynewt-core/net/nimble/host/services/ans\" - \"@apache-mynewt-core/net/nimble/host/services/gap\" - \"@apache-mynewt-core/net/nimble/host/services/gatt\" - \"@apache-mynewt-core/net/nimble/host/store/ram\" - \"@apache-mynewt-core/net/nimble/transport/ram\" - \"@apache-mynewt-core/sys/console/full\" - \"@apache-mynewt-core/sys/log/full\" - \"@apache-mynewt-core/sys/stats/full\" - \"@apache-mynewt-core/sys/sysinit\" - \"@apache-mynewt-core/sys/id\" - libs/my_drivers/myadc Creating the ADC Task Now that the driver is done, we'll need to add calls to the main app's main.c file, as well as a few other things. First, we'll need to update the includes, and add a task for our ADC sampling. #include \"myadc/myadc.h\" ... /* ADC Task settings */ #define ADC_TASK_PRIO 5 #define ADC_STACK_SIZE (OS_STACK_ALIGN(336)) struct os_eventq adc_evq ; struct os_task adc_task ; bssnz_t os_stack_t adc_stack [ ADC_STACK_SIZE ]; Next we'll need o initialize the task event_q so we'll add the highlighted code to main() as shown below: /* Set the default device name. */ rc = ble_svc_gap_device_name_set ( \"nimble-adc\" ); assert ( rc == 0 ); conf_load (); /* Initialize adc sensor task eventq */ os_eventq_init ( &adc_evq ); /* Create the ADC reader task. * All sensor operations are performed in this task. */ os_task_init ( &adc_task , \"sensor\" , adc_task_handler , NULL , ADC_TASK_PRIO , OS_WAIT_FOREVER , adc_stack , ADC_STACK_SIZE ); We'll need that adc_task_handler() function to exist, and that's where we'll initialize the ADC Device and set the event handler. In the task's while() loop, we'll just make a call to adc_sample() to cause the ADC driver to sample the adc device. /** * Event loop for the sensor task. */ static void adc_task_handler ( void *unused ) { struct adc_dev *adc ; int rc ; /* ADC init */ adc = adc_init (); rc = adc_event_handler_set ( adc , adc_read_event , ( void * ) NULL ); assert ( rc == 0 ); while ( 1 ) { adc_sample ( adc ); /* Wait 2 second */ os_time_delay ( OS_TICKS_PER_SEC * 2 ); } } Above the adc_task_handler , add code to handle the adc_read_event() calls: int adc_read_event ( struct adc_dev *dev , void *arg , uint8_t etype , void *buffer , int buffer_len ) { int value ; uint16_t chr_val_handle ; int rc ; value = adc_read ( buffer , buffer_len ); if ( value >= 0 ) { console_printf ( \"Got %d\\n\" , value ); } else { console_printf ( \"Error while reading: %d\\n\" , value ); goto err ; } gatt_adc_val = value ; rc = ble_gatts_find_chr ( &gatt_svr_svc_adc_uuid . u , BLE_UUID16_DECLARE ( ADC_SNS_VAL ), NULL , &chr_val_handle ); assert ( rc == 0 ); ble_gatts_chr_updated ( chr_val_handle ); return ( 0 ); err : return ( rc ); } This is where we actually read the ADC value and then update the BLE Characteristic for that value. But wait, we haven't defined those BLE services and characteristics yet! Right, so don't try to build and run this app just yet or it will surely fail. Instead, move on to the next section and get all of those services defined. Building the BLE Services If the nrf52_adc app is going to be a Bluetooth-enabled sensor app that will allow you to read the value of the eTape Water Level Sensor via Bluetooth we'll need to actually define those Services and Characteristics. As with the ble peripheral app, we will advertise a couple of values from our app. The first is not strictly necessary, but it will help us build an iOS app later. We've defined a service and the characteristics in that service in bleadc.h in the apps/nrf52_adc/src/ directory as follows: /* Sensor Data */ /* e761d2af-1c15-4fa7-af80-b5729002b340 */ static const ble_uuid128_t gatt_svr_svc_adc_uuid = BLE_UUID128_INIT ( 0x40 , 0xb3 , 0x20 , 0x90 , 0x72 , 0xb5 , 0x80 , 0xaf , 0xa7 , 0x4f , 0x15 , 0x1c , 0xaf , 0xd2 , 0x61 , 0xe7 ); #define ADC_SNS_TYPE 0xDEAD #define ADC_SNS_STRING \"eTape Liquid Level Sensor\" #define ADC_SNS_VAL 0xBEAD extern uint16_t gatt_adc_val ; The first is the UUID of the service, followed by the 2 characteristics we are going to offer. The first characteristic is going to advertise the type of sensor we are advertising, and it will be a read-only characteristic. The second characteristic will be the sensor value itself, and we will allow connected devices to 'subscribe' to it in order to get constantly-updated values. Note: You can choose any valid Characteristic UUIDs to go here. We're using these values for illustrative purposes only. The value that we'll be updating is also defined here as gatt_adc_val . If we then go look at gatt_srv.c we can see the structure of the service and characteristic offering that we set up: static const struct ble_gatt_svc_def gatt_svr_svcs [] = { { /*** Service: Security test. */ . type = BLE_GATT_SVC_TYPE_PRIMARY , . uuid = &gatt_svr_svc_sec_test_uuid . u , . characteristics = ( struct ble_gatt_chr_def []) { { /*** Characteristic: Random number generator. */ . uuid = &gatt_svr_chr_sec_test_rand_uuid . u , . access_cb = gatt_svr_chr_access_sec_test , . flags = BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_READ_ENC , }, { /*** Characteristic: Static value. */ . uuid = &gatt_svr_chr_sec_test_static_uuid . u , . access_cb = gatt_svr_chr_access_sec_test , . flags = BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_WRITE | BLE_GATT_CHR_F_WRITE_ENC , }, { 0 , /* No more characteristics in this service. */ } }, }, { /*** ADC Level Notification Service. */ . type = BLE_GATT_SVC_TYPE_PRIMARY , . uuid = &gatt_svr_svc_adc_uuid . u , . characteristics = ( struct ble_gatt_chr_def []) { { . uuid = BLE_UUID16_DECLARE ( ADC_SNS_TYPE ), . access_cb = gatt_svr_sns_access , . flags = BLE_GATT_CHR_F_READ , }, { . uuid = BLE_UUID16_DECLARE ( ADC_SNS_VAL ), . access_cb = gatt_svr_sns_access , . flags = BLE_GATT_CHR_F_NOTIFY , }, { 0 , /* No more characteristics in this service. */ } }, }, { 0 , /* No more services. */ }, }; You should recognize the first services from the BLE Peripheral tutorial earlier. We're just adding another Service, with 2 new Characteristics, to that application. We'll need to fill in the function that will be called for this service, gatt_srv_sns_access next so that the service knows what to do. static int gatt_svr_sns_access ( uint16_t conn_handle , uint16_t attr_handle , struct ble_gatt_access_ctxt *ctxt , void *arg ) { uint16_t uuid16 ; int rc ; uuid16 = ble_uuid_u16 ( ctxt->chr->uuid ); switch ( uuid16 ) { case ADC_SNS_TYPE : assert ( ctxt->op == BLE_GATT_ACCESS_OP_READ_CHR ); rc = os_mbuf_append ( ctxt->om , ADC_SNS_STRING , sizeof ADC_SNS_STRING ); BLEPRPH_LOG ( INFO , \"ADC SENSOR TYPE READ: %s\\n\" , ADC_SNS_STRING ); return rc == 0 ? 0 : BLE_ATT_ERR_INSUFFICIENT_RES ; case ADC_SNS_VAL : if ( ctxt->op == BLE_GATT_ACCESS_OP_WRITE_CHR ) { rc = gatt_svr_chr_write ( ctxt->om , 0 , sizeof gatt_adc_val , &gatt_adc_val , NULL ); return rc ; } else if ( ctxt->op == BLE_GATT_ACCESS_OP_READ_CHR ) { rc = os_mbuf_append ( ctxt->om , &gatt_adc_val , sizeof gatt_adc_val ); return rc == 0 ? 0 : BLE_ATT_ERR_INSUFFICIENT_RES ; } default : assert ( 0 ); return BLE_ATT_ERR_UNLIKELY ; } } You can see that when request is for the ADC_SNS_TYPE , we return the Sensor Type we defined earlier. If the request if for ADC_SNS_VAL we'll return the gatt_adc_val value. Don't forget to include the bleadc.h include file at the top of the gatt_svr.c file! #include <assert.h> #include <stdio.h> #include <string.h> #include \"bsp/bsp.h\" #include \"host/ble_hs.h\" #include \"host/ble_uuid.h\" #include \"bleprph.h\" #include \"bleadc.h\" If you build, load and run this application now, you will see all those Services and Characteristics advertised, and you will even be able to read the \"Sensor Type\" String via the ADC_SNS_TYPE Characteristic. Adding the eTape Water Sensor Now that we have a fully functioning BLE App that we can subscribe to sensor values from, it's time to actually wire up the sensor! As previously mentioned, we're going to be using an eTape Water Level Sensor. You can get one from Adafruit . We're going to use the sensor as a resistive sensor, and the setup is very simple. I'll be using a 'breadboard` to put this all together for illustrative purposes. First, attach a jumper-wire from Vdd on the board to the breadboard. Next, attach a jumper wire from pin P0.03 on the board to the breadboard. This will be our ADC-in. The sensor should have come with a 560 ohm resistor, so plug that into the board between Vdd and ADC-in holes. Finally, attach a jumper from GND on the board to your breadboard. At this point, your breadboard should look like this: Now attach one of the middle 2 leads from the sensor to ground on the breadboard and the other middle lead to the ADC-in on the breadboard. Your breadboard should now look like this: And your eTape Sensor should look like this (at least if you have it mounted in a graduated cylinder as I do). That concludes the hardware portion. Easy! At this point you should be able to build, create-image and load your application and see it properly sending readings. Conclusion Congratulations, you've now completed both a hardware project and a software project by connecting a sensor to your device and using Mynewt to read data from that sensor and send it via Bluetooth to a connected device. That's no small feat! If you see anything missing or want to send us feedback, please do so by signing up for appropriate mailing lists on our Community Page . Keep on hacking and sensing! Note If you're wondering how to actually view these sensor readings via Bluetooth, you have a couple of options. On Mac OS or iOS you can download the LightBlue app . This app lets you connect to, and interrogate, BLE devices like the one you just built. If you used the BLE Service and Characteristic UUIDs used in this tutorial, you can also download and use a Mac OS MyNewt Sensor Reader App (Zip Archive) that allows you to graph your data, etc. An iOS version is in Beta testing and should be available soon. Enjoy!","title":"Add an Analog Sensor"},{"location":"os/tutorials/nrf52_adc/#adding-an-analog-sensor-on-nrf52","text":"","title":"Adding an Analog Sensor on nRF52"},{"location":"os/tutorials/nrf52_adc/#objective","text":"We will be adding an analog sensor to the NRF52DK development board and using the Analog to Digital Converter (ADC) to read the values from the sensor. It's also using Bluetooth to allow you to connect to the app and read the value of the sensor. Please see the following section for the required hardware in order to complete this tutorial.","title":"Objective"},{"location":"os/tutorials/nrf52_adc/#hardware-needed","text":"nRF52 Development Kit (one of the following) Dev Kit from Nordic - PCA 10040 Eval Kit from Rigado - BMD-300-EVAL-ES eTape Liquid Sensor -- buy from Adafruit Laptop running Mac OS It is assumed you have already installed newt tool. It is assumed you already installed native tools as described here","title":"Hardware needed"},{"location":"os/tutorials/nrf52_adc/#create-a-project","text":"Create a new project to hold your work. For a deeper understanding, you can read about project creation in Get Started -- Creating Your First Project or just follow the commands below. $ mkdir ~/dev $ cd ~/dev $ newt new myadc Downloading project skeleton from apache/incubator-mynewt-blinky... Installing skeleton in myadc... Project myadc successfully created. $ cd myadc","title":"Create a project."},{"location":"os/tutorials/nrf52_adc/#add-additional-repositories","text":"The board-specific libraries for the NRF52dk board are in an external repository at present, so you'll need to include that remote repository and install it as well. If you're not familiar with using repositories, see the section on repositories before continuing. Or just copy and paste the following. In your project.yml file, add mynewt_nordic to the project.repositories section, and then add the proper repository definition. When you're done, your project.yml file should look like this: project.name: \"my_project\" project.repositories: - apache-mynewt-core - mynewt_nordic # Use github's distribution mechanism for core ASF libraries. # This provides mirroring automatically for us. # repository.apache-mynewt-core: type: github vers: 1-latest user: apache repo: incubator-mynewt-core repository.mynewt_nordic: type: github vers: 1-latest user: runtimeco repo: mynewt_nordic","title":"Add Additional Repositories"},{"location":"os/tutorials/nrf52_adc/#install-everything","text":"Now that you have defined the needed repositories, it's time to install everything so that you can get started. $ newt install -v apache-mynewt-core Downloading repository description for apache-mynewt-core... success! ... apache-mynewt-core successfully installed version 0.9.0-none ... mynewt_nordic Downloading repository description for mynewt_nordic... success! ... mynewt_nordic successfully installed version 0.9.9-none","title":"Install Everything"},{"location":"os/tutorials/nrf52_adc/#create-the-targets","text":"Create two targets - one for the bootloader and one for the nrf52 board. Note: The correct bsp must be chosen for the board you are using. For the Nordic Dev Kit choose @apache-mynewt-core/hw/bsp/nrf52dk instead (in the highlighted lines) For the Rigado Eval Kit choose @apache-mynewt-core/hw/bsp/bmd300eval instead (in the highlighted lines) For the app itself we're going to extend the bleprph app so that we get the Bluetooth communications built in, so the first thing we'll need to do is copy that app into our own app directory: $ mkdir -p apps/nrf52_adc $ cp -Rp repos/apache-mynewt-core/apps/bleprph/* apps/nrf52_adc Next, you'll modify the pkg.yml file for your app. Note the change in pkg.name and pkg.description . Also make sure that you specify the full path of all the packages with the prefix @apache-mynewt-core/ as shown in the third highlighted line. $ cat apps/nrf52_adc/pkg.yml ... pkg.name: apps/nrf52_adc pkg.type: app pkg.description: Simple BLE peripheral application for ADC Sensors. pkg.author: \"Apache Mynewt <dev@mynewt.incubator.apache.org>\" pkg.homepage: \"http://mynewt.apache.org/\" pkg.keywords: pkg.deps: - \"@apache-mynewt-core/boot/split\" - \"@apache-mynewt-core/kernel/os\" - \"@apache-mynewt-core/mgmt/imgmgr\" - \"@apache-mynewt-core/mgmt/newtmgr\" - \"@apache-mynewt-core/mgmt/newtmgr/transport/ble\" - \"@apache-mynewt-core/net/nimble/controller\" - \"@apache-mynewt-core/net/nimble/host\" - \"@apache-mynewt-core/net/nimble/host/services/ans\" - \"@apache-mynewt-core/net/nimble/host/services/gap\" - \"@apache-mynewt-core/net/nimble/host/services/gatt\" - \"@apache-mynewt-core/net/nimble/host/store/ram\" - \"@apache-mynewt-core/net/nimble/transport/ram\" - \"@apache-mynewt-core/sys/console/full\" - \"@apache-mynewt-core/sys/log/full\" - \"@apache-mynewt-core/sys/stats/full\" - \"@apache-mynewt-core/sys/sysinit\" - \"@apache-mynewt-core/sys/id\" Great! We have our very own app so let's make sure we have all of our targets set correctly: $ newt target create nrf52_adc $ newt target set nrf52_adc app=apps/nrf52_adc Target targets/nrf52_adc successfully set target.app to apps/nrf52_adc $ newt target set nrf52_adc bsp=@apache-mynewt-core/hw/bsp/nrf52dk $ newt target set nrf52_adc build_profile=debug $ newt target create nrf52_boot $ newt target set nrf52_boot app=@apache-mynewt-core/apps/boot $ newt target set nrf52_boot bsp=@apache-mynewt-core/hw/bsp/nrf52dk $ newt target set nrf52_boot build_profile=optimized $ newt target show targets/nrf52_adc app=apps/nrf52_adc bsp=@apache-mynewt-core/hw/bsp/nrf52dk build_profile=debug targets/nrf52_boot app=@apache-mynewt-core/apps/boot bsp=@apache-mynewt-core/hw/bsp/nrf52dk build_profile=optimized Note: If you've already built and installed a bootloader for your NRF52dk then you do not need to create a target for it here, or build and load it as below.","title":"Create the targets"},{"location":"os/tutorials/nrf52_adc/#build-the-target-executables","text":"$ newt build nrf52_boot ... Compiling boot.c Archiving boot.a Linking boot.elf App successfully built: ~/dev/myadc/bin/nrf52_boot/apps/boot/boot.elf $ newt build nrf52_adc ... Compiling main.c Archiving nrf52_adc.a Linking nrf52_adc.elf App successfully built: ~/dev/myadc/bin/nrf52_adc/apps/nrf52_adc/nrf52_adc.elf","title":"Build the target executables"},{"location":"os/tutorials/nrf52_adc/#sign-and-create-the-nrf52_adc-application-image","text":"You must sign and version your application image to download it using newt to the board. Use the newt create-image command to perform this action. You may assign an arbitrary version (e.g. 1.0.0) to the image. $ newt create-image nrf52_adc 1.0.0 App image successfully generated: ~/dev/myadc/bin/nrf52_adc/apps/nrf52_adc/nrf52_adc.img Build manifest: ~/dev/myadc/bin/nrf52_adc/apps/nrf52_adc/manifest.json","title":"Sign and create the nrf52_adc application image"},{"location":"os/tutorials/nrf52_adc/#connect-the-board","text":"Connect the evaluation board via micro-USB to your PC via USB cable.","title":"Connect the board"},{"location":"os/tutorials/nrf52_adc/#download-to-the-target","text":"Download the bootloader first and then the nrf52_adc executable to the target platform. Don't forget to reset the board if you don't see the LED blinking right away! $ newt load nrf52_boot $ newt load nrf52_adc Note: If you want to erase the flash and load the image again, you can use JLinkExe to issue an erase command. $ JLinkExe -device nRF52 -speed 4000 -if SWD SEGGER J-Link Commander V5.12c (Compiled Apr 21 2016 16:05:51) DLL version V5.12c, compiled Apr 21 2016 16:05:45 Connecting to J-Link via USB...O.K. Firmware: J-Link OB-SAM3U128-V2-NordicSemi compiled Mar 15 2016 18:03:17 Hardware version: V1.00 S/N: 682863966 VTref = 3.300V Type \"connect\" to establish a target connection, '?' for help J-Link>erase Cortex-M4 identified. Erasing device (0;?i?)... Comparing flash [100%] Done. Erasing flash [100%] Done. Verifying flash [100%] Done. J-Link: Flash download: Total time needed: 0.363s (Prepare: 0.093s, Compare: 0.000s, Erase: 0.262s, Program: 0.000s, Verify: 0.000s, Restore: 0.008s) Erasing done. J-Link>exit $ So you have a BLE app, but really all you've done is change the name of the bleprph app to nrf52_adc and load that. Not all that impressive, and it certainly won't read an Analog Sensor right now. So let's do that next. In order to read an ADC sensor, and since the ADC package is in an external, licensed, repository, we'll create a driver for it here in our app that will leverage the existing driver in the external repository. It adds another layer of indirection, but it will also give us a look at building our own driver, so we'll do it this way.","title":"Download to the target"},{"location":"os/tutorials/nrf52_adc/#building-a-driver","text":"The first thing to do is to create the directory structure for your driver: [user@IsMyLaptop:~/src/air_quality]$ mkdir -p libs/my_drivers/myadc/include/myadc [user@IsMyLaptop:~/src/air_quality]$ mkdir -p libs/my_drivers/myadc/src Now you can add the files you need. You'll need a pkg.yml to describe the driver, and then header stub followed by source stub. [user@IsMyLaptop:~/src/air_quality]$ cat libs/my_drivers/myadc/pkg.yml # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you 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. # pkg . name: libs/my_drivers/myadc pkg . deps: - \"@apache-mynewt-core/hw/hal\" - \"@mynewt_nordic/hw/drivers/adc/adc_nrf52\" First, let's create the required header file myadc.h in the includes directory i.e. libs/my_drivers/myadc/include/myadc/myadc.h . It's a pretty straightforward header file, since we only need to do 2 things: Initialize the ADC device Read ADC Values #ifndef _NRF52_ADC_H_ #define _NRF52_ADC_H_ void * adc_init ( void ); int adc_read ( void *buffer , int buffer_len ); #endif /* _NRF52_ADC_H_ */ Next we'll need a corresponding source file myadc.c in the src directory. This is where we'll implement the specifics of the driver: #include <assert.h> #include <os/os.h> /* ADC */ #include \"myadc/myadc.h\" #include \"nrf.h\" #include \"app_util_platform.h\" #include \"app_error.h\" #include <adc/adc.h> #include <adc_nrf52/adc_nrf52.h> #include \"nrf_drv_saadc.h\" #define ADC_NUMBER_SAMPLES (2) #define ADC_NUMBER_CHANNELS (1) nrf_drv_saadc_config_t adc_config = NRF_DRV_SAADC_DEFAULT_CONFIG ; struct adc_dev *adc ; uint8_t *sample_buffer1 ; uint8_t *sample_buffer2 ; static struct adc_dev os_bsp_adc0 ; static nrf_drv_saadc_config_t os_bsp_adc0_config = { . resolution = MYNEWT_VAL ( ADC_0_RESOLUTION ), . oversample = MYNEWT_VAL ( ADC_0_OVERSAMPLE ), . interrupt_priority = MYNEWT_VAL ( ADC_0_INTERRUPT_PRIORITY ), }; void * adc_init ( void ) { int rc = 0 ; rc = os_dev_create (( struct os_dev * ) &os_bsp_adc0 , \"adc0\" , OS_DEV_INIT_KERNEL , OS_DEV_INIT_PRIO_DEFAULT , nrf52_adc_dev_init , &os_bsp_adc0_config ); assert ( rc == 0 ); nrf_saadc_channel_config_t cc = NRF_DRV_SAADC_DEFAULT_CHANNEL_CONFIG_SE ( NRF_SAADC_INPUT_AIN1 ); cc . gain = NRF_SAADC_GAIN1_6 ; cc . reference = NRF_SAADC_REFERENCE_INTERNAL ; adc = ( struct adc_dev * ) os_dev_open ( \"adc0\" , 0 , &adc_config ); assert ( adc != NULL ); adc_chan_config ( adc , 0 , &cc ); sample_buffer1 = malloc ( adc_buf_size ( adc , ADC_NUMBER_CHANNELS , ADC_NUMBER_SAMPLES )); sample_buffer2 = malloc ( adc_buf_size ( adc , ADC_NUMBER_CHANNELS , ADC_NUMBER_SAMPLES )); memset ( sample_buffer1 , 0 , adc_buf_size ( adc , ADC_NUMBER_CHANNELS , ADC_NUMBER_SAMPLES )); memset ( sample_buffer2 , 0 , adc_buf_size ( adc , ADC_NUMBER_CHANNELS , ADC_NUMBER_SAMPLES )); adc_buf_set ( adc , sample_buffer1 , sample_buffer2 , adc_buf_size ( adc , ADC_NUMBER_CHANNELS , ADC_NUMBER_SAMPLES )); return adc ; } int adc_read ( void *buffer , int buffer_len ) { int i ; int adc_result ; int my_result_mv = 0 ; int rc ; for ( i = 0 ; i < ADC_NUMBER_SAMPLES ; i++ ) { rc = adc_buf_read ( adc , buffer , buffer_len , i , &adc_result ); if ( rc != 0 ) { goto err ; } my_result_mv = adc_result_mv ( adc , 0 , adc_result ); } adc_buf_release ( adc , buffer , buffer_len ); return my_result_mv ; err : return ( rc ); } There's a lot going on in here, so let's walk through it step by step. First, we define a default configuration, with the resolution, oversample and interrupt priority. You'll see that these are MYNEWT_VAL values, which means that we'll define them shortly in a syscfg.yml file to be passed to the compiler at build time. static struct adc_dev os_bsp_adc0 ; static nrf_drv_saadc_config_t os_bsp_adc0_config = { . resolution = MYNEWT_VAL ( ADC_0_RESOLUTION ), . oversample = MYNEWT_VAL ( ADC_0_OVERSAMPLE ), . interrupt_priority = MYNEWT_VAL ( ADC_0_INTERRUPT_PRIORITY ), }; Next, in adc_init() , we need to tell the OS to create the device. void * adc_init ( void ) { int rc = 0 ; rc = os_dev_create (( struct os_dev * ) &os_bsp_adc0 , \"adc0\" , OS_DEV_INIT_KERNEL , OS_DEV_INIT_PRIO_DEFAULT , nrf52_adc_dev_init , &os_bsp_adc0_config ); assert ( rc == 0 ); nrf_saadc_channel_config_t cc = NRF_DRV_SAADC_DEFAULT_CHANNEL_CONFIG_SE ( NRF_SAADC_INPUT_AIN1 ); cc . gain = NRF_SAADC_GAIN1_6 ; cc . reference = NRF_SAADC_REFERENCE_INTERNAL ; adc = ( struct adc_dev * ) os_dev_open ( \"adc0\" , 0 , &adc_config ); assert ( adc != NULL ); adc_chan_config ( adc , 0 , &cc ); sample_buffer1 = malloc ( adc_buf_size ( adc , ADC_NUMBER_CHANNELS , ADC_NUMBER_SAMPLES )); sample_buffer2 = malloc ( adc_buf_size ( adc , ADC_NUMBER_CHANNELS , ADC_NUMBER_SAMPLES )); memset ( sample_buffer1 , 0 , adc_buf_size ( adc , ADC_NUMBER_CHANNELS , ADC_NUMBER_SAMPLES )); memset ( sample_buffer2 , 0 , adc_buf_size ( adc , ADC_NUMBER_CHANNELS , ADC_NUMBER_SAMPLES )); adc_buf_set ( adc , sample_buffer1 , sample_buffer2 , adc_buf_size ( adc , ADC_NUMBER_CHANNELS , ADC_NUMBER_SAMPLES )); return adc ; } A few things need to be said about this part, as it is the most confusing. First, we're using a default configuration for the ADC Channel via the NRF_DRV_SAADC_DEFAULT_CHANNEL_CONFIG_SE macro. The important part here is that we're actually using AIN1 . I know what you're thinking, \"But we want ADC-0!\" and that's true. The board is actually labelled 'A0, A1, A2' etc., and the actual pin numbers are also listed on the board, which seems handy. At first. But it gets messy very quickly. If you try to use AIN0, and then go poke around in the registers while this is running, (gdb) p/x {NRF_SAADC_Type}0x40007000 ... CH = {{ PSELP = 0x1, PSELN = 0x0, CONFIG = 0x20000, LIMIT = 0x7fff8000 }, You'll see that the pin for channel 0 is set to 1, which corresponds to AIN0, but that's NOT the same as A0 -- pin P0.03, the one we're using. For that, you use AIN1, which would set the pin value to 2. Messy. Someone, somewhere, thought this made sense. The only other thing to note here is that we're using the internal reference voltage, rather than setting our own. There's nothing wrong with that, but since we are, we'll have to crank up the gain a bit by using NRF_SAADC_GAIN1_6 . Then, in adc_read() we will take readings, convert the raw readings to a millivolt equivalent, and return the result. int adc_read ( void *buffer , int buffer_len ) { int i ; int adc_result ; int my_result_mv = 0 ; int rc ; for ( i = 0 ; i < ADC_NUMBER_SAMPLES ; i++ ) { rc = adc_buf_read ( adc , buffer , buffer_len , i , &adc_result ); if ( rc != 0 ) { goto err ; } my_result_mv = adc_result_mv ( adc , 0 , adc_result ); } adc_buf_release ( adc , buffer , buffer_len ); return my_result_mv ; err : return ( rc ); } Finally, we'll need some settings for our driver, as mentioned earlier. In the myadc directory you'll need to add a syscfg.yml file: # Package: libs/my_driver/myadc syscfg.defs: ADC_0: description: 'TBD' value: 1 ADC_0_RESOLUTION: description: 'TBD' value: 'SAADC_CONFIG_RESOLUTION' ADC_0_OVERSAMPLE: description: 'TBD' value: 'SAADC_CONFIG_OVERSAMPLE' ADC_0_INTERRUPT_PRIORITY: description: 'TBD' value: 'SAADC_CONFIG_IRQ_PRIORITY' Once that's all done, you should have a working ADC Driver for your NRF52DK board. The last step in getting the driver set up is to include it in the package dependency defined by pkg.deps in the pkg.yml file of your app. Add it in apps/nrf52_adc/pkg.yml as shown by the highlighted line below. # Licensed to the Apache Software Foundation (ASF) under one # <snip> pkg.name: apps/nrf52_adc pkg.type: app pkg.description: Simple BLE peripheral application for ADC sensor. pkg.author: \"Apache Mynewt <dev@mynewt.incubator.apache.org>\" pkg.homepage: \"http://mynewt.apache.org/\" pkg.keywords: pkg.deps: - \"@apache-mynewt-core/boot/split\" - \"@apache-mynewt-core/kernel/os\" - \"@apache-mynewt-core/mgmt/imgmgr\" - \"@apache-mynewt-core/mgmt/newtmgr\" - \"@apache-mynewt-core/mgmt/newtmgr/transport/ble\" - \"@apache-mynewt-core/net/nimble/controller\" - \"@apache-mynewt-core/net/nimble/host\" - \"@apache-mynewt-core/net/nimble/host/services/ans\" - \"@apache-mynewt-core/net/nimble/host/services/gap\" - \"@apache-mynewt-core/net/nimble/host/services/gatt\" - \"@apache-mynewt-core/net/nimble/host/store/ram\" - \"@apache-mynewt-core/net/nimble/transport/ram\" - \"@apache-mynewt-core/sys/console/full\" - \"@apache-mynewt-core/sys/log/full\" - \"@apache-mynewt-core/sys/stats/full\" - \"@apache-mynewt-core/sys/sysinit\" - \"@apache-mynewt-core/sys/id\" - libs/my_drivers/myadc","title":"Building a Driver"},{"location":"os/tutorials/nrf52_adc/#creating-the-adc-task","text":"Now that the driver is done, we'll need to add calls to the main app's main.c file, as well as a few other things. First, we'll need to update the includes, and add a task for our ADC sampling. #include \"myadc/myadc.h\" ... /* ADC Task settings */ #define ADC_TASK_PRIO 5 #define ADC_STACK_SIZE (OS_STACK_ALIGN(336)) struct os_eventq adc_evq ; struct os_task adc_task ; bssnz_t os_stack_t adc_stack [ ADC_STACK_SIZE ]; Next we'll need o initialize the task event_q so we'll add the highlighted code to main() as shown below: /* Set the default device name. */ rc = ble_svc_gap_device_name_set ( \"nimble-adc\" ); assert ( rc == 0 ); conf_load (); /* Initialize adc sensor task eventq */ os_eventq_init ( &adc_evq ); /* Create the ADC reader task. * All sensor operations are performed in this task. */ os_task_init ( &adc_task , \"sensor\" , adc_task_handler , NULL , ADC_TASK_PRIO , OS_WAIT_FOREVER , adc_stack , ADC_STACK_SIZE ); We'll need that adc_task_handler() function to exist, and that's where we'll initialize the ADC Device and set the event handler. In the task's while() loop, we'll just make a call to adc_sample() to cause the ADC driver to sample the adc device. /** * Event loop for the sensor task. */ static void adc_task_handler ( void *unused ) { struct adc_dev *adc ; int rc ; /* ADC init */ adc = adc_init (); rc = adc_event_handler_set ( adc , adc_read_event , ( void * ) NULL ); assert ( rc == 0 ); while ( 1 ) { adc_sample ( adc ); /* Wait 2 second */ os_time_delay ( OS_TICKS_PER_SEC * 2 ); } } Above the adc_task_handler , add code to handle the adc_read_event() calls: int adc_read_event ( struct adc_dev *dev , void *arg , uint8_t etype , void *buffer , int buffer_len ) { int value ; uint16_t chr_val_handle ; int rc ; value = adc_read ( buffer , buffer_len ); if ( value >= 0 ) { console_printf ( \"Got %d\\n\" , value ); } else { console_printf ( \"Error while reading: %d\\n\" , value ); goto err ; } gatt_adc_val = value ; rc = ble_gatts_find_chr ( &gatt_svr_svc_adc_uuid . u , BLE_UUID16_DECLARE ( ADC_SNS_VAL ), NULL , &chr_val_handle ); assert ( rc == 0 ); ble_gatts_chr_updated ( chr_val_handle ); return ( 0 ); err : return ( rc ); } This is where we actually read the ADC value and then update the BLE Characteristic for that value. But wait, we haven't defined those BLE services and characteristics yet! Right, so don't try to build and run this app just yet or it will surely fail. Instead, move on to the next section and get all of those services defined.","title":"Creating the ADC Task"},{"location":"os/tutorials/nrf52_adc/#building-the-ble-services","text":"If the nrf52_adc app is going to be a Bluetooth-enabled sensor app that will allow you to read the value of the eTape Water Level Sensor via Bluetooth we'll need to actually define those Services and Characteristics. As with the ble peripheral app, we will advertise a couple of values from our app. The first is not strictly necessary, but it will help us build an iOS app later. We've defined a service and the characteristics in that service in bleadc.h in the apps/nrf52_adc/src/ directory as follows: /* Sensor Data */ /* e761d2af-1c15-4fa7-af80-b5729002b340 */ static const ble_uuid128_t gatt_svr_svc_adc_uuid = BLE_UUID128_INIT ( 0x40 , 0xb3 , 0x20 , 0x90 , 0x72 , 0xb5 , 0x80 , 0xaf , 0xa7 , 0x4f , 0x15 , 0x1c , 0xaf , 0xd2 , 0x61 , 0xe7 ); #define ADC_SNS_TYPE 0xDEAD #define ADC_SNS_STRING \"eTape Liquid Level Sensor\" #define ADC_SNS_VAL 0xBEAD extern uint16_t gatt_adc_val ; The first is the UUID of the service, followed by the 2 characteristics we are going to offer. The first characteristic is going to advertise the type of sensor we are advertising, and it will be a read-only characteristic. The second characteristic will be the sensor value itself, and we will allow connected devices to 'subscribe' to it in order to get constantly-updated values. Note: You can choose any valid Characteristic UUIDs to go here. We're using these values for illustrative purposes only. The value that we'll be updating is also defined here as gatt_adc_val . If we then go look at gatt_srv.c we can see the structure of the service and characteristic offering that we set up: static const struct ble_gatt_svc_def gatt_svr_svcs [] = { { /*** Service: Security test. */ . type = BLE_GATT_SVC_TYPE_PRIMARY , . uuid = &gatt_svr_svc_sec_test_uuid . u , . characteristics = ( struct ble_gatt_chr_def []) { { /*** Characteristic: Random number generator. */ . uuid = &gatt_svr_chr_sec_test_rand_uuid . u , . access_cb = gatt_svr_chr_access_sec_test , . flags = BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_READ_ENC , }, { /*** Characteristic: Static value. */ . uuid = &gatt_svr_chr_sec_test_static_uuid . u , . access_cb = gatt_svr_chr_access_sec_test , . flags = BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_WRITE | BLE_GATT_CHR_F_WRITE_ENC , }, { 0 , /* No more characteristics in this service. */ } }, }, { /*** ADC Level Notification Service. */ . type = BLE_GATT_SVC_TYPE_PRIMARY , . uuid = &gatt_svr_svc_adc_uuid . u , . characteristics = ( struct ble_gatt_chr_def []) { { . uuid = BLE_UUID16_DECLARE ( ADC_SNS_TYPE ), . access_cb = gatt_svr_sns_access , . flags = BLE_GATT_CHR_F_READ , }, { . uuid = BLE_UUID16_DECLARE ( ADC_SNS_VAL ), . access_cb = gatt_svr_sns_access , . flags = BLE_GATT_CHR_F_NOTIFY , }, { 0 , /* No more characteristics in this service. */ } }, }, { 0 , /* No more services. */ }, }; You should recognize the first services from the BLE Peripheral tutorial earlier. We're just adding another Service, with 2 new Characteristics, to that application. We'll need to fill in the function that will be called for this service, gatt_srv_sns_access next so that the service knows what to do. static int gatt_svr_sns_access ( uint16_t conn_handle , uint16_t attr_handle , struct ble_gatt_access_ctxt *ctxt , void *arg ) { uint16_t uuid16 ; int rc ; uuid16 = ble_uuid_u16 ( ctxt->chr->uuid ); switch ( uuid16 ) { case ADC_SNS_TYPE : assert ( ctxt->op == BLE_GATT_ACCESS_OP_READ_CHR ); rc = os_mbuf_append ( ctxt->om , ADC_SNS_STRING , sizeof ADC_SNS_STRING ); BLEPRPH_LOG ( INFO , \"ADC SENSOR TYPE READ: %s\\n\" , ADC_SNS_STRING ); return rc == 0 ? 0 : BLE_ATT_ERR_INSUFFICIENT_RES ; case ADC_SNS_VAL : if ( ctxt->op == BLE_GATT_ACCESS_OP_WRITE_CHR ) { rc = gatt_svr_chr_write ( ctxt->om , 0 , sizeof gatt_adc_val , &gatt_adc_val , NULL ); return rc ; } else if ( ctxt->op == BLE_GATT_ACCESS_OP_READ_CHR ) { rc = os_mbuf_append ( ctxt->om , &gatt_adc_val , sizeof gatt_adc_val ); return rc == 0 ? 0 : BLE_ATT_ERR_INSUFFICIENT_RES ; } default : assert ( 0 ); return BLE_ATT_ERR_UNLIKELY ; } } You can see that when request is for the ADC_SNS_TYPE , we return the Sensor Type we defined earlier. If the request if for ADC_SNS_VAL we'll return the gatt_adc_val value. Don't forget to include the bleadc.h include file at the top of the gatt_svr.c file! #include <assert.h> #include <stdio.h> #include <string.h> #include \"bsp/bsp.h\" #include \"host/ble_hs.h\" #include \"host/ble_uuid.h\" #include \"bleprph.h\" #include \"bleadc.h\" If you build, load and run this application now, you will see all those Services and Characteristics advertised, and you will even be able to read the \"Sensor Type\" String via the ADC_SNS_TYPE Characteristic.","title":"Building the BLE Services"},{"location":"os/tutorials/nrf52_adc/#adding-the-etape-water-sensor","text":"Now that we have a fully functioning BLE App that we can subscribe to sensor values from, it's time to actually wire up the sensor! As previously mentioned, we're going to be using an eTape Water Level Sensor. You can get one from Adafruit . We're going to use the sensor as a resistive sensor, and the setup is very simple. I'll be using a 'breadboard` to put this all together for illustrative purposes. First, attach a jumper-wire from Vdd on the board to the breadboard. Next, attach a jumper wire from pin P0.03 on the board to the breadboard. This will be our ADC-in. The sensor should have come with a 560 ohm resistor, so plug that into the board between Vdd and ADC-in holes. Finally, attach a jumper from GND on the board to your breadboard. At this point, your breadboard should look like this: Now attach one of the middle 2 leads from the sensor to ground on the breadboard and the other middle lead to the ADC-in on the breadboard. Your breadboard should now look like this: And your eTape Sensor should look like this (at least if you have it mounted in a graduated cylinder as I do). That concludes the hardware portion. Easy! At this point you should be able to build, create-image and load your application and see it properly sending readings.","title":"Adding the eTape Water Sensor"},{"location":"os/tutorials/nrf52_adc/#conclusion","text":"Congratulations, you've now completed both a hardware project and a software project by connecting a sensor to your device and using Mynewt to read data from that sensor and send it via Bluetooth to a connected device. That's no small feat! If you see anything missing or want to send us feedback, please do so by signing up for appropriate mailing lists on our Community Page . Keep on hacking and sensing!","title":"Conclusion"},{"location":"os/tutorials/nrf52_adc/#note","text":"If you're wondering how to actually view these sensor readings via Bluetooth, you have a couple of options. On Mac OS or iOS you can download the LightBlue app . This app lets you connect to, and interrogate, BLE devices like the one you just built. If you used the BLE Service and Characteristic UUIDs used in this tutorial, you can also download and use a Mac OS MyNewt Sensor Reader App (Zip Archive) that allows you to graph your data, etc. An iOS version is in Beta testing and should be available soon. Enjoy!","title":"Note"},{"location":"os/tutorials/olimex/","text":"Blinky, your \"Hello World!\", on Olimex This tutorial shows you how to create, build, and run the Blinky application on an Olimex STM32-E407 board. Prerequisites Meet the prerequisites listed in Project Blinky . Have a STM32-E407 development board from Olimex. Have a ARM-USB-TINY-H connector with JTAG interface for debugging ARM microcontrollers (comes with the ribbon cable to hook up to the board) Have a USB A-B type cable to connect the debugger to your computer. Install the OpenOCD debugger . Create a Project Create a new project if you do not have an existing one. You can skip this step and proceed to create the targets if you already created a project. Run the following commands to create a new project: $ mkdir ~/dev $ cd ~/dev $ newt new myproj Downloading project skeleton from apache/incubator-mynewt-blinky... Installing skeleton in myproj... Project myproj successfully created. $cd myproj $ newt install apache-mynewt-core $ Create the Targets Create two targets for the Olimex board - one for the bootloader and one for the Blinky application. Run the following newt target commands, from your project directory, to create a bootloader target. We name the target boot_olimex . $ newt target create boot_olimex $ newt target set boot_olimex build_profile=optimized $ newt target set boot_olimex app=@apache-mynewt-core/apps/boot $ newt target set boot_olimex bsp=@apache-mynewt-core/hw/bsp/olimex_stm32-e407_devboard Run the following newt target commands to create a target for the Blinky application. We name the target olimex_blinky . $ newt target create olimex_blinky $ newt target set olimex_blinky build_profile=debug $ newt target set olimex_blinky bsp=@apache-mynewt-core/hw/bsp/olimex_stm32-e407_devboard $ newt target set olimex_blinky app=apps/blinky Build the Bootloader Run the newt build boot_olimex command to build the bootloader: $ newt build boot_olimex Building target targets/boot_olimex Compiling repos/apache-mynewt-core/boot/bootutil/src/image_ec256.c Compiling repos/apache-mynewt-core/boot/bootutil/src/image_ec.c Compiling repos/apache-mynewt-core/boot/bootutil/src/image_rsa.c Compiling bin/targets/boot_olimex/generated/src/boot_olimex-sysflash.c ... Archiving libc_baselibc.a Archiving sys_flash_map.a Archiving sys_mfg.a Archiving sys_sysinit.a Archiving util_mem.a Linking ~/dev/myproj/bin/targets/boot_olimex/app/apps/boot/boot.elf Target successfully built: targets/boot_olimex Build the Blinky Application Run the newt build olimex_blinky command to build the blinky application: $ newt build olimex_blinky Building target targets/olimex_blinky Assembling repos/apache-mynewt-core/hw/bsp/olimex_stm32-e407_devboard/src/arch/cortex_m4/startup_STM32F40x.s Compiling repos/apache-mynewt-core/hw/drivers/uart/src/uart.c Compiling repos/apache-mynewt-core/hw/cmsis-core/src/cmsis_nvic.c Compiling repos/apache-mynewt-core/hw/bsp/olimex_stm32-e407_devboard/src/sbrk.c Compiling apps/blinky/src/main.c Compiling repos/apache-mynewt-core/hw/drivers/uart/uart_hal/src/uart_hal.c Compiling repos/apache-mynewt-core/hw/bsp/olimex_stm32-e407_devboard/src/hal_bsp.c Compiling repos/apache-mynewt-core/hw/bsp/olimex_stm32-e407_devboard/src/system_stm32f4xx.c Compiling repos/apache-mynewt-core/hw/hal/src/hal_common.c Compiling repos/apache-mynewt-core/hw/hal/src/hal_flash.c ... Archiving sys_mfg.a Archiving sys_sysinit.a Archiving util_mem.a Linking ~/dev/myproj/bin/targets/olimex_blinky/app/apps/blinky/blinky.elf Target successfully built: targets/olimex_blinky Sign and Create the Blinky Application Image Run the newt create-image olimex_blinky 1.0.0 command to sign and create an image file for the blinky application. You may assign an arbitrary version (e.g. 1.0.0) number. $ newt create-image olimex_blinky 1.0.0 App image succesfully generated: ~/dev/myproj/bin/targets/olimex_blinky/app/apps/blinky/blinky.img Connect to the Board Configure the board to bootload from flash memory and to use USB-OTG2 for the power source. Refer to the following diagrams to locate the boot jumpers and power input select jumpers on the board. Note: The labels for the USB-OTG1 and USB-OTG2 ports on the diagram are reversed. The port labeled USB-OTG1 on the diagram is the USB-OTG2 port and the port labeled USB-OTG2 on the diagram is the USB-OTG1 port. Locate the boot jumpers on the lower right corner of the board. B1_1/B1_0 and B0_1/B0_0 are PTH jumpers to control the boot mode when a bootloader is present. These two jumpers must be moved together. The board searches for the bootloader in three places: User Flash Memory, System Memory or the Embedded SRAM. For this Blinky project, we configure the board to boot from flash by jumpering B0_0 and B1_0 . Note: The markings on the board may not always be accurate, and you should always refer to the manual for the correct positioning. Locate the Power Input Select jumpers on the lower left corner of the board. Set the Power Select jumpers to position 5 and 6 to use the USB-OTG2 port for the power source. If you would like to use a different power source, refer to the OLIMEX STM32-E407 user manual for pin specifications. Connect the USB Micro-A cable to the USB-OTG2 port on the board. Connect the JTAG connector to the JTAG/SWD interface on the board. Connect the USB A-B cable to the ARM-USB-TINY-H connector and your computer. Check that the red PWR LED lights up. Load the Bootloader and Blinky Application Run the newt load boot_olimex command to load the bootloader image onto the board: $newt load -v boot_olimex Loading bootloader Load command: ~/dev/myproj/repos/apache-mynewt-core/hw/bsp/olimex_stm32-e407_devboard/olimex_stm32-e407_devboard_download.sh ~/dev/myproj/repos/apache-mynewt-core/hw/bsp/olimex_stm32-e407_devboard ~/dev/myproj/bin/targets/boot_olimex/app/apps/boot/boot Successfully loaded image. Note: If you are using Windows and get a no device found error, you will need to install the usb driver. Download Zadig and run it: Select Options > List All Devices. Select Olimex OpenOCD JTAG ARM-USB-TINY-H from the drop down menu. Select the WinUSB driver. Click Install Driver. Run the newt load boot_olimex command again. Run the newt load olimex_blinky command to load the blinky application image onto the board: newt load -v olimex_blinky Loading app image into slot 1 Load command: ~/dev/myproj/repos/apache-mynewt-core/hw/bsp/olimex_stm32-e407_devboard/olimex_stm32-e407_devboard_download.sh ~/dev/myproj/repos/apache-mynewt-core/hw/bsp/olimex_stm32-e407_devboard ~/dev/myproj/bin/targets/olimex_blinky/app/apps/blinky/blinky Successfully loaded image. The LED should be blinking! Let's double check that it is indeed booting from flash and making the LED blink from the image in flash. Pull the USB cable off the Olimex JTAG adaptor, severing the debug connection to the JTAG port. Next power off the Olimex board by pulling out the USB cable from the board. Wait for a couple of seconds and plug the USB cable back to the board. The LED light will start blinking again. Success! If you want to download the image to flash and open a gdb session, use newt debug blinky . Note: The output of the debug session below is for Mac OS and Linux platforms. On Windows, openocd and gdb are started in separate Windows Command Prompt terminals, and the terminals are automatically closed when you quit gdb. In addition, the output of openocd is logged to the openocd.log file in your project's base directory instead of the terminal. Type c to continue inside the gdb session. $ newt debug blinky Debugging with ~/dev/myproj/hw/bsp/olimex_stm32-e407_... Debugging ~/dev/myproj/project/blinky/bin/blinky/blinky.elf GNU gdb (GNU Tools for ARM Embedded Processors) 7.8.0.20150604-cvs Copyright (C) 2014 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 <http://gnu.org/licenses/gpl.html> ... (info) ... target state: halted target halted due to debug-request, current mode: Thread xPSR: 0x01000000 pc: 0x08000250 msp: 0x10010000 Info : accepting 'gdb' connection from 3333 Info : device id = 0x10036413 Info : flash size = 1024kbytes Reset_Handler () at startup_STM32F40x.s:199 199 ldr r1, =__etext (gdb) If you want to erase the flash and load the image again you may use the following commands from within gdb. flash erase_sector 0 0 x tells it to erase sectors 0 through x. When you ask it to display (in hex notation) the contents of the sector starting at location 'lma,' you should see all f's. The memory location 0x8000000 is the start or origin of the flash memory contents and is specified in the olimex_stm32-e407_devboard.ld linker script. The flash memory locations is specific to the processor. (gdb) monitor flash erase_sector 0 0 4 erased sectors 0 through 4 on flash bank 0 in 2.296712s (gdb) monitor mdw 0x08000000 16 0x08000000: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff (0x08000020: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff (0x08000000: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff (0x08000020: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff (gdb) monitor flash info 0","title":"Blinky on Olimex"},{"location":"os/tutorials/olimex/#blinky-your-hello-world-on-olimex","text":"This tutorial shows you how to create, build, and run the Blinky application on an Olimex STM32-E407 board.","title":"Blinky, your \"Hello World!\", on Olimex"},{"location":"os/tutorials/olimex/#prerequisites","text":"Meet the prerequisites listed in Project Blinky . Have a STM32-E407 development board from Olimex. Have a ARM-USB-TINY-H connector with JTAG interface for debugging ARM microcontrollers (comes with the ribbon cable to hook up to the board) Have a USB A-B type cable to connect the debugger to your computer. Install the OpenOCD debugger .","title":"Prerequisites"},{"location":"os/tutorials/olimex/#create-a-project","text":"Create a new project if you do not have an existing one. You can skip this step and proceed to create the targets if you already created a project. Run the following commands to create a new project: $ mkdir ~/dev $ cd ~/dev $ newt new myproj Downloading project skeleton from apache/incubator-mynewt-blinky... Installing skeleton in myproj... Project myproj successfully created. $cd myproj $ newt install apache-mynewt-core $","title":"Create a Project"},{"location":"os/tutorials/olimex/#create-the-targets","text":"Create two targets for the Olimex board - one for the bootloader and one for the Blinky application. Run the following newt target commands, from your project directory, to create a bootloader target. We name the target boot_olimex . $ newt target create boot_olimex $ newt target set boot_olimex build_profile=optimized $ newt target set boot_olimex app=@apache-mynewt-core/apps/boot $ newt target set boot_olimex bsp=@apache-mynewt-core/hw/bsp/olimex_stm32-e407_devboard Run the following newt target commands to create a target for the Blinky application. We name the target olimex_blinky . $ newt target create olimex_blinky $ newt target set olimex_blinky build_profile=debug $ newt target set olimex_blinky bsp=@apache-mynewt-core/hw/bsp/olimex_stm32-e407_devboard $ newt target set olimex_blinky app=apps/blinky","title":"Create the Targets"},{"location":"os/tutorials/olimex/#build-the-bootloader","text":"Run the newt build boot_olimex command to build the bootloader: $ newt build boot_olimex Building target targets/boot_olimex Compiling repos/apache-mynewt-core/boot/bootutil/src/image_ec256.c Compiling repos/apache-mynewt-core/boot/bootutil/src/image_ec.c Compiling repos/apache-mynewt-core/boot/bootutil/src/image_rsa.c Compiling bin/targets/boot_olimex/generated/src/boot_olimex-sysflash.c ... Archiving libc_baselibc.a Archiving sys_flash_map.a Archiving sys_mfg.a Archiving sys_sysinit.a Archiving util_mem.a Linking ~/dev/myproj/bin/targets/boot_olimex/app/apps/boot/boot.elf Target successfully built: targets/boot_olimex","title":"Build the Bootloader"},{"location":"os/tutorials/olimex/#build-the-blinky-application","text":"Run the newt build olimex_blinky command to build the blinky application: $ newt build olimex_blinky Building target targets/olimex_blinky Assembling repos/apache-mynewt-core/hw/bsp/olimex_stm32-e407_devboard/src/arch/cortex_m4/startup_STM32F40x.s Compiling repos/apache-mynewt-core/hw/drivers/uart/src/uart.c Compiling repos/apache-mynewt-core/hw/cmsis-core/src/cmsis_nvic.c Compiling repos/apache-mynewt-core/hw/bsp/olimex_stm32-e407_devboard/src/sbrk.c Compiling apps/blinky/src/main.c Compiling repos/apache-mynewt-core/hw/drivers/uart/uart_hal/src/uart_hal.c Compiling repos/apache-mynewt-core/hw/bsp/olimex_stm32-e407_devboard/src/hal_bsp.c Compiling repos/apache-mynewt-core/hw/bsp/olimex_stm32-e407_devboard/src/system_stm32f4xx.c Compiling repos/apache-mynewt-core/hw/hal/src/hal_common.c Compiling repos/apache-mynewt-core/hw/hal/src/hal_flash.c ... Archiving sys_mfg.a Archiving sys_sysinit.a Archiving util_mem.a Linking ~/dev/myproj/bin/targets/olimex_blinky/app/apps/blinky/blinky.elf Target successfully built: targets/olimex_blinky","title":"Build the Blinky Application"},{"location":"os/tutorials/olimex/#sign-and-create-the-blinky-application-image","text":"Run the newt create-image olimex_blinky 1.0.0 command to sign and create an image file for the blinky application. You may assign an arbitrary version (e.g. 1.0.0) number. $ newt create-image olimex_blinky 1.0.0 App image succesfully generated: ~/dev/myproj/bin/targets/olimex_blinky/app/apps/blinky/blinky.img","title":"Sign and Create the Blinky Application Image"},{"location":"os/tutorials/olimex/#connect-to-the-board","text":"Configure the board to bootload from flash memory and to use USB-OTG2 for the power source. Refer to the following diagrams to locate the boot jumpers and power input select jumpers on the board. Note: The labels for the USB-OTG1 and USB-OTG2 ports on the diagram are reversed. The port labeled USB-OTG1 on the diagram is the USB-OTG2 port and the port labeled USB-OTG2 on the diagram is the USB-OTG1 port. Locate the boot jumpers on the lower right corner of the board. B1_1/B1_0 and B0_1/B0_0 are PTH jumpers to control the boot mode when a bootloader is present. These two jumpers must be moved together. The board searches for the bootloader in three places: User Flash Memory, System Memory or the Embedded SRAM. For this Blinky project, we configure the board to boot from flash by jumpering B0_0 and B1_0 . Note: The markings on the board may not always be accurate, and you should always refer to the manual for the correct positioning. Locate the Power Input Select jumpers on the lower left corner of the board. Set the Power Select jumpers to position 5 and 6 to use the USB-OTG2 port for the power source. If you would like to use a different power source, refer to the OLIMEX STM32-E407 user manual for pin specifications. Connect the USB Micro-A cable to the USB-OTG2 port on the board. Connect the JTAG connector to the JTAG/SWD interface on the board. Connect the USB A-B cable to the ARM-USB-TINY-H connector and your computer. Check that the red PWR LED lights up.","title":"Connect to the Board"},{"location":"os/tutorials/olimex/#load-the-bootloader-and-blinky-application","text":"Run the newt load boot_olimex command to load the bootloader image onto the board: $newt load -v boot_olimex Loading bootloader Load command: ~/dev/myproj/repos/apache-mynewt-core/hw/bsp/olimex_stm32-e407_devboard/olimex_stm32-e407_devboard_download.sh ~/dev/myproj/repos/apache-mynewt-core/hw/bsp/olimex_stm32-e407_devboard ~/dev/myproj/bin/targets/boot_olimex/app/apps/boot/boot Successfully loaded image. Note: If you are using Windows and get a no device found error, you will need to install the usb driver. Download Zadig and run it: Select Options > List All Devices. Select Olimex OpenOCD JTAG ARM-USB-TINY-H from the drop down menu. Select the WinUSB driver. Click Install Driver. Run the newt load boot_olimex command again. Run the newt load olimex_blinky command to load the blinky application image onto the board: newt load -v olimex_blinky Loading app image into slot 1 Load command: ~/dev/myproj/repos/apache-mynewt-core/hw/bsp/olimex_stm32-e407_devboard/olimex_stm32-e407_devboard_download.sh ~/dev/myproj/repos/apache-mynewt-core/hw/bsp/olimex_stm32-e407_devboard ~/dev/myproj/bin/targets/olimex_blinky/app/apps/blinky/blinky Successfully loaded image. The LED should be blinking! Let's double check that it is indeed booting from flash and making the LED blink from the image in flash. Pull the USB cable off the Olimex JTAG adaptor, severing the debug connection to the JTAG port. Next power off the Olimex board by pulling out the USB cable from the board. Wait for a couple of seconds and plug the USB cable back to the board. The LED light will start blinking again. Success! If you want to download the image to flash and open a gdb session, use newt debug blinky . Note: The output of the debug session below is for Mac OS and Linux platforms. On Windows, openocd and gdb are started in separate Windows Command Prompt terminals, and the terminals are automatically closed when you quit gdb. In addition, the output of openocd is logged to the openocd.log file in your project's base directory instead of the terminal. Type c to continue inside the gdb session. $ newt debug blinky Debugging with ~/dev/myproj/hw/bsp/olimex_stm32-e407_... Debugging ~/dev/myproj/project/blinky/bin/blinky/blinky.elf GNU gdb (GNU Tools for ARM Embedded Processors) 7.8.0.20150604-cvs Copyright (C) 2014 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 <http://gnu.org/licenses/gpl.html> ... (info) ... target state: halted target halted due to debug-request, current mode: Thread xPSR: 0x01000000 pc: 0x08000250 msp: 0x10010000 Info : accepting 'gdb' connection from 3333 Info : device id = 0x10036413 Info : flash size = 1024kbytes Reset_Handler () at startup_STM32F40x.s:199 199 ldr r1, =__etext (gdb) If you want to erase the flash and load the image again you may use the following commands from within gdb. flash erase_sector 0 0 x tells it to erase sectors 0 through x. When you ask it to display (in hex notation) the contents of the sector starting at location 'lma,' you should see all f's. The memory location 0x8000000 is the start or origin of the flash memory contents and is specified in the olimex_stm32-e407_devboard.ld linker script. The flash memory locations is specific to the processor. (gdb) monitor flash erase_sector 0 0 4 erased sectors 0 through 4 on flash bank 0 in 2.296712s (gdb) monitor mdw 0x08000000 16 0x08000000: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff (0x08000020: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff (0x08000000: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff (0x08000020: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff (gdb) monitor flash info 0","title":"Load the Bootloader and Blinky Application"},{"location":"os/tutorials/pin-wheel-mods/","text":"Pin Wheel Modifications to \"Blinky\" on STM32F3 Discovery Objective Learn how to modify an existing app -- the blinky app -- to light all the LEDs on the STM32F3 Discovery board. What you need Discovery kit with STM32F303VC MCU Laptop running Mac OSX. It is assumed you have already installed and run the blinky app succesfully. Since you've already successfully created your blinky app project, you'll need to modify only one file, main.c, in order to get this app working. The main.c file resides in the apps/blinky/src directory in your project folder so you can edit it with your favorite editor. You'll make the following changes: Replace the line: int g_led_pin ; With the line: int g_led_pins [ 8 ] = { LED_BLINK_PIN_1 , LED_BLINK_PIN_2 , LED_BLINK_PIN_3 , LED_BLINK_PIN_4 , LED_BLINK_PIN_5 , LED_BLINK_PIN_6 , LED_BLINK_PIN_7 , LED_BLINK_PIN_8 }; So that you now have an array of all 8 LED Pins on the board. Delete the line: g_led_pin = LED_BLINK_PIN ; And in its place, add the following lines to initialize all the LED_PINS correctly: int x ; for ( x = 0 ; x < 8 ; x++ ){ hal_gpio_init_out ( g_led_pins [ x ], 1 ); } int p = 0 ; We'll use that 'p' later. Next you'll want to change the line: os_time_delay ( 1000 ); to a shorter time in order to make it a little more interesting. A full 1 second delay doesn't look great, so try 100 for starters and then you can adjust it to your liking. Finally, change the line: hal_gpio_toggle ( g_led_pin ); to look like this: hal_gpio_toggle ( g_led_pins [ p++ ]); p = ( p > 7 ) ? 0 : p ; Build the target and executables and download the images Run the same commands you used on the blinky app to build and load this one: $ newt create-image stmf3_blinky 1.2.3 App image successfully generated: ~/dev/myproj/bin/stmf3_blinky/apps/blinky/blinky.img Build manifest:~/dev/myproj/bin/stmf3_blinky/apps/blinky/manifest.json $ newt -v load stmf3_boot $ newt -v load stmf3_blinky Watch the LEDs go round and round The colored LEDs should now all light up in succession, and once they're all lit, they should then go off in the same order. This should repeat continuously. If you see anything missing or want to send us feedback, please do so by signing up for appropriate mailing lists on our Community Page . Keep on hacking and blinking!","title":"Pin wheel mods"},{"location":"os/tutorials/pin-wheel-mods/#pin-wheel-modifications-to-blinky-on-stm32f3-discovery","text":"","title":"Pin Wheel Modifications to \"Blinky\" on STM32F3 Discovery"},{"location":"os/tutorials/pin-wheel-mods/#objective","text":"Learn how to modify an existing app -- the blinky app -- to light all the LEDs on the STM32F3 Discovery board.","title":"Objective"},{"location":"os/tutorials/pin-wheel-mods/#what-you-need","text":"Discovery kit with STM32F303VC MCU Laptop running Mac OSX. It is assumed you have already installed and run the blinky app succesfully. Since you've already successfully created your blinky app project, you'll need to modify only one file, main.c, in order to get this app working. The main.c file resides in the apps/blinky/src directory in your project folder so you can edit it with your favorite editor. You'll make the following changes: Replace the line: int g_led_pin ; With the line: int g_led_pins [ 8 ] = { LED_BLINK_PIN_1 , LED_BLINK_PIN_2 , LED_BLINK_PIN_3 , LED_BLINK_PIN_4 , LED_BLINK_PIN_5 , LED_BLINK_PIN_6 , LED_BLINK_PIN_7 , LED_BLINK_PIN_8 }; So that you now have an array of all 8 LED Pins on the board. Delete the line: g_led_pin = LED_BLINK_PIN ; And in its place, add the following lines to initialize all the LED_PINS correctly: int x ; for ( x = 0 ; x < 8 ; x++ ){ hal_gpio_init_out ( g_led_pins [ x ], 1 ); } int p = 0 ; We'll use that 'p' later. Next you'll want to change the line: os_time_delay ( 1000 ); to a shorter time in order to make it a little more interesting. A full 1 second delay doesn't look great, so try 100 for starters and then you can adjust it to your liking. Finally, change the line: hal_gpio_toggle ( g_led_pin ); to look like this: hal_gpio_toggle ( g_led_pins [ p++ ]); p = ( p > 7 ) ? 0 : p ;","title":"What you need"},{"location":"os/tutorials/pin-wheel-mods/#build-the-target-and-executables-and-download-the-images","text":"Run the same commands you used on the blinky app to build and load this one: $ newt create-image stmf3_blinky 1.2.3 App image successfully generated: ~/dev/myproj/bin/stmf3_blinky/apps/blinky/blinky.img Build manifest:~/dev/myproj/bin/stmf3_blinky/apps/blinky/manifest.json $ newt -v load stmf3_boot $ newt -v load stmf3_blinky","title":"Build the target and executables and download the images"},{"location":"os/tutorials/pin-wheel-mods/#watch-the-leds-go-round-and-round","text":"The colored LEDs should now all light up in succession, and once they're all lit, they should then go off in the same order. This should repeat continuously. If you see anything missing or want to send us feedback, please do so by signing up for appropriate mailing lists on our Community Page . Keep on hacking and blinking!","title":"Watch the LEDs go round and round"},{"location":"os/tutorials/project-nrf52-slinky/","text":"Project Slinky using the Nordic nRF52 Board This tutorial shows you how to create, build and run the Slinky application and communicate with newtmgr for a Nordic nRF52 board. Prerequisites Meet the prerequisites listed in Project Slinky . Have a Nordic nRF52-DK board. Install the Segger JLINK Software and documentation pack . Create a New Project Create a new project if you do not have an existing one. You can skip this step and proceed to create the targets if you already have a project created or completed the Sim Slinky tutorial. Run the following commands to create a new project. We name the project slinky . $ newt new slinky Downloading project skeleton from apache/incubator-mynewt-blinky... ... Installing skeleton in slink... Project slinky successfully created $ cd slinky $newt install apache-mynewt-core Create the Targets Create two targets for the nRF52-DK board - one for the bootloader and one for the Slinky application. Run the following newt target commands, from your project directory, to create a bootloader target. We name the target nrf52_boot . $ newt target create nrf52_boot $ newt target set nrf52_boot bsp=@apache-mynewt-core/hw/bsp/nrf52dk $ newt target set nrf52_boot build_profile=optimized $ newt target set nrf52_boot app=@apache-mynewt-core/apps/boot Run the following newt target commands to create a target for the Slinky application. We name the target nrf52_slinky . $ newt target create nrf52_slinky $ newt target set nrf52_slinky bsp=@apache-mynewt-core/hw/bsp/nrf52dk $ newt target set nrf52_slinky build_profile=debug $ newt target set nrf52_slinky app=@apache-mynewt-core/apps/slinky Build the Targets Run the newt build nrf52_boot command to build the bootloader: $ newt build nrf52-boot Building target targets/nrf52_boot Compiling repos/apache-mynewt-core/boot/bootutil/src/image_ec256.c Compiling repos/apache-mynewt-core/boot/bootutil/src/image_ec.c Compiling repos/apache-mynewt-core/boot/bootutil/src/image_rsa.c Compiling repos/apache-mynewt-core/crypto/mbedtls/src/aes.c Compiling repos/apache-mynewt-core/boot/bootutil/src/loader.c Compiling repos/apache-mynewt-core/boot/bootutil/src/image_validate.c Compiling repos/apache-mynewt-core/boot/bootutil/src/bootutil_misc.c Compiling repos/apache-mynewt-core/apps/boot/src/boot.c ... Archiving sys_mfg.a Archiving sys_sysinit.a Archiving util_mem.a Linking ~/dev/slinky/bin/targets/nrf52_boot/app/apps/boot/boot.elf Target successfully built: targets/nrf52_boot Run the newt build nrf52_slinky command to build the Slinky application: $newt build nrf52_slinky Building target targets/nrf52_slinky Compiling repos/apache-mynewt-core/boot/bootutil/src/image_ec256.c Compiling repos/apache-mynewt-core/boot/bootutil/src/image_ec.c Compiling repos/apache-mynewt-core/boot/bootutil/src/image_rsa.c Compiling repos/apache-mynewt-core/boot/split/src/split.c Compiling repos/apache-mynewt-core/boot/bootutil/src/loader.c Compiling repos/apache-mynewt-core/boot/bootutil/src/bootutil_misc.c Compiling repos/apache-mynewt-core/boot/split/src/split_config.c Compiling repos/apache-mynewt-core/crypto/mbedtls/src/aesni.c Compiling repos/apache-mynewt-core/boot/bootutil/src/image_validate.c Compiling repos/apache-mynewt-core/crypto/mbedtls/src/aes.c Compiling repos/apache-mynewt-core/apps/slinky/src/main.c ... Archiving util_mem.a Linking ~/dev/slinky/bin/targets/nrf52_slinky/app/apps/slinky/slinky.elf Target successfully built: targets/nrf52_slinky Sign and Create the Slinky Application Image Run the newt create-image nrf52_slinky 1.0.0 command to create and sign the application image. You may assign an arbitrary version (e.g. 1.0.0) to the image. $ newt create-image nrf52_slinky 1.0.0 App image succesfully generated: ~/dev/slinky/bin/targets/nrf52_slinky/app/apps/slinky/slinky.img $ Connect to the Board Connect a micro-USB cable from your computer to the micro-USB port on the nRF52-DK board. Turn the power on the board to ON. You should see the green LED light up on the board. Load the Bootloader and the Slinky Application Image Run the newt load nrf52_boot command to load the bootloader onto the board: $ newt load nrf52_boot Loading bootloader $ Run the newt load nrf52_slinky command to load the Slinky application image onto the board: $ newt load nrf52_slinky Loading app image into slot 1 $ Connect Newtmgr with the Board using a Serial Connection Set up a serial connection from your computer to the nRF52-DK board (See Serial Port Setup ). Locate the port, in the /dev directory on your computer, that the serial connection uses. The format of the port name is platform dependent: Mac OS uses the format tty.usbserial-<some identifier> . Linux uses the format TTYUSB<N> , where N is a number. For example, TTYUSB2. MinGW on Windows uses the format ttyS<N> , where N is a number. You must map the port name to a Windows COM port: /dev/ttyS<N> maps to COM<N+1> . For example, /dev/ttyS2 maps to COM3 . You can also use the Windows Device Manager to find the COM port number. $ ls /dev/tty*usbserial* /dev/tty.usbserial-1d11 $ Setup a newtmgr connection profile for the serial port. For our example, the port is /dev/tty.usbserial-1d11 . Run the newtmgr conn add command to define a newtmgr connection profile for the serial port. We name the connection profile nrf52serial . Note : You will need to replace the connstring with the specific port for your serial connection. On Windows, you must specify COM<N+1> for the connstring if /dev/ttyS<N> is the serial port. $ newtmgr conn add nrf52serial type=serial connstring=/dev/tty.usbserial-1d11 Connection profile nrf52serial successfully added $ You can run the newt conn show command to see all the newtmgr connection profiles: $ newtmgr conn show Connection profiles: nrf52serial: type=serial, connstring='/dev/tty.usbserial-1d11' sim1: type=serial, connstring='/dev/ttys012' $ Use Newtmgr to Query the Board Run some newtmgr commands to query and receive responses back from the board (See the Newt Manager Guide for more information on the newtmgr commands). Run the newtmgr echo hello -c nrf52serial command. This is the simplest command that requests the board to echo back the text. $ newtmgr echo hello -c nrf52serial hello $ Run the newtmgr image list -c nrf52serial command to list the images on the board: $ newtmgr image list -c nrf52serial Images: slot=0 version: 1.0.0 bootable: true flags: active confirmed hash: f411a55d7a5f54eb8880d380bf47521d8c41ed77fd0a7bd5373b0ae87ddabd42 Split status: N/A $ Run the newtmgr taskstats -c nrf52serial command to display the task statistics on the board: $ newtmgr taskstats -c nrf52serial Return Code = 0 task pri tid runtime csw stksz stkuse last_checkin next_checkin task1 8 2 0 1751 192 110 0 0 task2 9 3 0 1751 64 31 0 0 idle 255 0 224081 2068 64 32 0 0 main 127 1 3 29 1024 365 0 0 $","title":"Slinky on Nordic nRF52"},{"location":"os/tutorials/project-nrf52-slinky/#project-slinky-using-the-nordic-nrf52-board","text":"This tutorial shows you how to create, build and run the Slinky application and communicate with newtmgr for a Nordic nRF52 board.","title":"Project Slinky using the Nordic nRF52 Board"},{"location":"os/tutorials/project-nrf52-slinky/#prerequisites","text":"Meet the prerequisites listed in Project Slinky . Have a Nordic nRF52-DK board. Install the Segger JLINK Software and documentation pack .","title":"Prerequisites"},{"location":"os/tutorials/project-nrf52-slinky/#create-a-new-project","text":"Create a new project if you do not have an existing one. You can skip this step and proceed to create the targets if you already have a project created or completed the Sim Slinky tutorial. Run the following commands to create a new project. We name the project slinky . $ newt new slinky Downloading project skeleton from apache/incubator-mynewt-blinky... ... Installing skeleton in slink... Project slinky successfully created $ cd slinky $newt install apache-mynewt-core","title":"Create a New Project"},{"location":"os/tutorials/project-nrf52-slinky/#create-the-targets","text":"Create two targets for the nRF52-DK board - one for the bootloader and one for the Slinky application. Run the following newt target commands, from your project directory, to create a bootloader target. We name the target nrf52_boot . $ newt target create nrf52_boot $ newt target set nrf52_boot bsp=@apache-mynewt-core/hw/bsp/nrf52dk $ newt target set nrf52_boot build_profile=optimized $ newt target set nrf52_boot app=@apache-mynewt-core/apps/boot Run the following newt target commands to create a target for the Slinky application. We name the target nrf52_slinky . $ newt target create nrf52_slinky $ newt target set nrf52_slinky bsp=@apache-mynewt-core/hw/bsp/nrf52dk $ newt target set nrf52_slinky build_profile=debug $ newt target set nrf52_slinky app=@apache-mynewt-core/apps/slinky","title":" Create the Targets"},{"location":"os/tutorials/project-nrf52-slinky/#build-the-targets","text":"Run the newt build nrf52_boot command to build the bootloader: $ newt build nrf52-boot Building target targets/nrf52_boot Compiling repos/apache-mynewt-core/boot/bootutil/src/image_ec256.c Compiling repos/apache-mynewt-core/boot/bootutil/src/image_ec.c Compiling repos/apache-mynewt-core/boot/bootutil/src/image_rsa.c Compiling repos/apache-mynewt-core/crypto/mbedtls/src/aes.c Compiling repos/apache-mynewt-core/boot/bootutil/src/loader.c Compiling repos/apache-mynewt-core/boot/bootutil/src/image_validate.c Compiling repos/apache-mynewt-core/boot/bootutil/src/bootutil_misc.c Compiling repos/apache-mynewt-core/apps/boot/src/boot.c ... Archiving sys_mfg.a Archiving sys_sysinit.a Archiving util_mem.a Linking ~/dev/slinky/bin/targets/nrf52_boot/app/apps/boot/boot.elf Target successfully built: targets/nrf52_boot Run the newt build nrf52_slinky command to build the Slinky application: $newt build nrf52_slinky Building target targets/nrf52_slinky Compiling repos/apache-mynewt-core/boot/bootutil/src/image_ec256.c Compiling repos/apache-mynewt-core/boot/bootutil/src/image_ec.c Compiling repos/apache-mynewt-core/boot/bootutil/src/image_rsa.c Compiling repos/apache-mynewt-core/boot/split/src/split.c Compiling repos/apache-mynewt-core/boot/bootutil/src/loader.c Compiling repos/apache-mynewt-core/boot/bootutil/src/bootutil_misc.c Compiling repos/apache-mynewt-core/boot/split/src/split_config.c Compiling repos/apache-mynewt-core/crypto/mbedtls/src/aesni.c Compiling repos/apache-mynewt-core/boot/bootutil/src/image_validate.c Compiling repos/apache-mynewt-core/crypto/mbedtls/src/aes.c Compiling repos/apache-mynewt-core/apps/slinky/src/main.c ... Archiving util_mem.a Linking ~/dev/slinky/bin/targets/nrf52_slinky/app/apps/slinky/slinky.elf Target successfully built: targets/nrf52_slinky","title":"Build the Targets"},{"location":"os/tutorials/project-nrf52-slinky/#sign-and-create-the-slinky-application-image","text":"Run the newt create-image nrf52_slinky 1.0.0 command to create and sign the application image. You may assign an arbitrary version (e.g. 1.0.0) to the image. $ newt create-image nrf52_slinky 1.0.0 App image succesfully generated: ~/dev/slinky/bin/targets/nrf52_slinky/app/apps/slinky/slinky.img $","title":"Sign and Create the Slinky Application Image"},{"location":"os/tutorials/project-nrf52-slinky/#connect-to-the-board","text":"Connect a micro-USB cable from your computer to the micro-USB port on the nRF52-DK board. Turn the power on the board to ON. You should see the green LED light up on the board.","title":"Connect to the Board"},{"location":"os/tutorials/project-nrf52-slinky/#load-the-bootloader-and-the-slinky-application-image","text":"Run the newt load nrf52_boot command to load the bootloader onto the board: $ newt load nrf52_boot Loading bootloader $ Run the newt load nrf52_slinky command to load the Slinky application image onto the board: $ newt load nrf52_slinky Loading app image into slot 1 $","title":"Load the Bootloader and the Slinky Application Image"},{"location":"os/tutorials/project-nrf52-slinky/#connect-newtmgr-with-the-board-using-a-serial-connection","text":"Set up a serial connection from your computer to the nRF52-DK board (See Serial Port Setup ). Locate the port, in the /dev directory on your computer, that the serial connection uses. The format of the port name is platform dependent: Mac OS uses the format tty.usbserial-<some identifier> . Linux uses the format TTYUSB<N> , where N is a number. For example, TTYUSB2. MinGW on Windows uses the format ttyS<N> , where N is a number. You must map the port name to a Windows COM port: /dev/ttyS<N> maps to COM<N+1> . For example, /dev/ttyS2 maps to COM3 . You can also use the Windows Device Manager to find the COM port number. $ ls /dev/tty*usbserial* /dev/tty.usbserial-1d11 $ Setup a newtmgr connection profile for the serial port. For our example, the port is /dev/tty.usbserial-1d11 . Run the newtmgr conn add command to define a newtmgr connection profile for the serial port. We name the connection profile nrf52serial . Note : You will need to replace the connstring with the specific port for your serial connection. On Windows, you must specify COM<N+1> for the connstring if /dev/ttyS<N> is the serial port. $ newtmgr conn add nrf52serial type=serial connstring=/dev/tty.usbserial-1d11 Connection profile nrf52serial successfully added $ You can run the newt conn show command to see all the newtmgr connection profiles: $ newtmgr conn show Connection profiles: nrf52serial: type=serial, connstring='/dev/tty.usbserial-1d11' sim1: type=serial, connstring='/dev/ttys012' $","title":"Connect Newtmgr with the Board using a Serial Connection"},{"location":"os/tutorials/project-nrf52-slinky/#use-newtmgr-to-query-the-board","text":"Run some newtmgr commands to query and receive responses back from the board (See the Newt Manager Guide for more information on the newtmgr commands). Run the newtmgr echo hello -c nrf52serial command. This is the simplest command that requests the board to echo back the text. $ newtmgr echo hello -c nrf52serial hello $ Run the newtmgr image list -c nrf52serial command to list the images on the board: $ newtmgr image list -c nrf52serial Images: slot=0 version: 1.0.0 bootable: true flags: active confirmed hash: f411a55d7a5f54eb8880d380bf47521d8c41ed77fd0a7bd5373b0ae87ddabd42 Split status: N/A $ Run the newtmgr taskstats -c nrf52serial command to display the task statistics on the board: $ newtmgr taskstats -c nrf52serial Return Code = 0 task pri tid runtime csw stksz stkuse last_checkin next_checkin task1 8 2 0 1751 192 110 0 0 task2 9 3 0 1751 64 31 0 0 idle 255 0 224081 2068 64 32 0 0 main 127 1 3 29 1024 365 0 0 $","title":"Use Newtmgr to Query the Board"},{"location":"os/tutorials/project-sim-slinky/","text":"Project Sim Slinky This tutorial shows you how to create, build and run the Slinky application and communicate with newtmgr for a simulated device. This is supported on Mac OS and Linux platforms. Prerequisites Meet the prerequisites listed in Project Slinky . Creating a new project Instructions for creating a project are located in the Basic Setup section of the Mynewt Documentation We will list only the steps here for brevity. We will name the project slinky . $ newt new slinky Downloading project skeleton from apache/incubator-mynewt-blinky... ... Installing skeleton in slink... Project slinky successfully created $ cd slinky $newt install apache-mynewt-core Setting up your target build Create a target for slinky using the native bsp. We will list only the steps and suppress the tool output here for brevity. $ newt target create sim_slinky $ newt target set sim_slinky bsp=@apache-mynewt-core/hw/bsp/native $ newt target set sim_slinky build_profile=debug $ newt target set sim_slinky app=@apache-mynewt-core/apps/slinky Building Your target To build your target, use newt build . When complete, an executable file is created. $ newt build sim_slinky Building target targets/sim_slinky Compiling repos/apache-mynewt-core/boot/bootutil/src/image_ec256.c Compiling repos/apache-mynewt-core/boot/bootutil/src/image_rsa.c Compiling repos/apache-mynewt-core/boot/bootutil/src/image_ec.c Compiling repos/apache-mynewt-core/boot/split/src/split.c Compiling repos/apache-mynewt-core/boot/bootutil/src/image_validate.c Compiling repos/apache-mynewt-core/boot/bootutil/src/loader.c Compiling repos/apache-mynewt-core/boot/bootutil/src/bootutil_misc.c Compiling repos/apache-mynewt-core/crypto/mbedtls/src/aesni.c Compiling repos/apache-mynewt-core/crypto/mbedtls/src/aes.c Compiling repos/apache-mynewt-core/boot/split/src/split_config.c Compiling repos/apache-mynewt-core/apps/slinky/src/main.c ... Archiving util_crc.a Archiving util_mem.a Linking ~/dev/slinky/bin/targets/sim_slinky/app/apps/slinky/slinky.elf Target successfully built: targets/sim_slinky Run the target Run the executable you have build for the simulated environment. The serial port name on which the simulated target is connected is shown in the output when mynewt slinky starts. $ ~/dev/slinky/bin/targets/sim_slinky/app/apps/slinky/slinky.elf uart0 at /dev/ttys005 In this example, the slinky app opened up a com port /dev/ttys005 for communications with newtmgr. NOTE: This application will block. You will need to open a new console (or execute this in another console) to continue the tutorial.* Setting up a connection profile You will now set up a connection profile using newtmgr for the serial port connection and start communicating with the simulated remote device. $ newtmgr conn add sim1 type=serial connstring=/dev/ttys005 Connection profile sim1 successfully added $ newtmgr conn show Connection profiles: sim1: type=serial, connstring='/dev/ttys005' Executing newtmgr commands with the target You can now use connection profile sim1 to talk to the running sim_slinky. As an example, we will query the running mynewt OS for the usage of its memory pools. $ newtmgr -c sim1 mpstats Return Code = 0 name blksz cnt free min msys_1 292 12 10 10 As a test command, you can send an arbitrary string to the target and it will echo that string back in a response to newtmgr. $ newtmgr -c sim1 echo \"Hello Mynewt\" Hello Mynewt In addition to these, you can also examine running tasks, statistics, logs, image status (not on sim), and configuration.","title":"Slinky on sim device"},{"location":"os/tutorials/project-sim-slinky/#project-sim-slinky","text":"This tutorial shows you how to create, build and run the Slinky application and communicate with newtmgr for a simulated device. This is supported on Mac OS and Linux platforms.","title":"Project Sim Slinky"},{"location":"os/tutorials/project-sim-slinky/#prerequisites","text":"Meet the prerequisites listed in Project Slinky .","title":"Prerequisites"},{"location":"os/tutorials/project-sim-slinky/#creating-a-new-project","text":"Instructions for creating a project are located in the Basic Setup section of the Mynewt Documentation We will list only the steps here for brevity. We will name the project slinky . $ newt new slinky Downloading project skeleton from apache/incubator-mynewt-blinky... ... Installing skeleton in slink... Project slinky successfully created $ cd slinky $newt install apache-mynewt-core","title":"Creating a new project"},{"location":"os/tutorials/project-sim-slinky/#setting-up-your-target-build","text":"Create a target for slinky using the native bsp. We will list only the steps and suppress the tool output here for brevity. $ newt target create sim_slinky $ newt target set sim_slinky bsp=@apache-mynewt-core/hw/bsp/native $ newt target set sim_slinky build_profile=debug $ newt target set sim_slinky app=@apache-mynewt-core/apps/slinky","title":"Setting up your target build"},{"location":"os/tutorials/project-sim-slinky/#building-your-target","text":"To build your target, use newt build . When complete, an executable file is created. $ newt build sim_slinky Building target targets/sim_slinky Compiling repos/apache-mynewt-core/boot/bootutil/src/image_ec256.c Compiling repos/apache-mynewt-core/boot/bootutil/src/image_rsa.c Compiling repos/apache-mynewt-core/boot/bootutil/src/image_ec.c Compiling repos/apache-mynewt-core/boot/split/src/split.c Compiling repos/apache-mynewt-core/boot/bootutil/src/image_validate.c Compiling repos/apache-mynewt-core/boot/bootutil/src/loader.c Compiling repos/apache-mynewt-core/boot/bootutil/src/bootutil_misc.c Compiling repos/apache-mynewt-core/crypto/mbedtls/src/aesni.c Compiling repos/apache-mynewt-core/crypto/mbedtls/src/aes.c Compiling repos/apache-mynewt-core/boot/split/src/split_config.c Compiling repos/apache-mynewt-core/apps/slinky/src/main.c ... Archiving util_crc.a Archiving util_mem.a Linking ~/dev/slinky/bin/targets/sim_slinky/app/apps/slinky/slinky.elf Target successfully built: targets/sim_slinky","title":"Building Your target"},{"location":"os/tutorials/project-sim-slinky/#run-the-target","text":"Run the executable you have build for the simulated environment. The serial port name on which the simulated target is connected is shown in the output when mynewt slinky starts. $ ~/dev/slinky/bin/targets/sim_slinky/app/apps/slinky/slinky.elf uart0 at /dev/ttys005 In this example, the slinky app opened up a com port /dev/ttys005 for communications with newtmgr. NOTE: This application will block. You will need to open a new console (or execute this in another console) to continue the tutorial.*","title":"Run the target"},{"location":"os/tutorials/project-sim-slinky/#setting-up-a-connection-profile","text":"You will now set up a connection profile using newtmgr for the serial port connection and start communicating with the simulated remote device. $ newtmgr conn add sim1 type=serial connstring=/dev/ttys005 Connection profile sim1 successfully added $ newtmgr conn show Connection profiles: sim1: type=serial, connstring='/dev/ttys005'","title":"Setting up a connection profile"},{"location":"os/tutorials/project-sim-slinky/#executing-newtmgr-commands-with-the-target","text":"You can now use connection profile sim1 to talk to the running sim_slinky. As an example, we will query the running mynewt OS for the usage of its memory pools. $ newtmgr -c sim1 mpstats Return Code = 0 name blksz cnt free min msys_1 292 12 10 10 As a test command, you can send an arbitrary string to the target and it will echo that string back in a response to newtmgr. $ newtmgr -c sim1 echo \"Hello Mynewt\" Hello Mynewt In addition to these, you can also examine running tasks, statistics, logs, image status (not on sim), and configuration.","title":"Executing newtmgr commands with the target"},{"location":"os/tutorials/project-slinky/","text":"Project Slinky The goal of the project is to use a sample application called \"Slinky\" included in the Mynewt repository to enable remote communications with a device running the Mynewt OS. The protocol for remote communications is called newt manager (newtmgr). If you have an existing project using a target that does not use the Slinky application and you wish to add newtmgr functionality to it, check out the tutorial titled Enable newtmgr in any app . Available Tutorials Tutorials are available for the following boards: Slinky on a simulated device . This is supported on Mac OS and Linux platforms. Slinky on a nRF52 . Slinky on an Olimex . Prerequisites Ensure that you meet the following prerequisites before continuing with this tutorial: Have Internet connectivity to fetch remote Mynewt components. Have a computer to build a Mynewt application and connect to the board over USB. Have a Micro-USB cable to connect the board and the computer. Have a serial port setup . Install the newt tool and the toolchains (See Basic Setup ). Install the newtmgr tool . Read the Mynewt OS Concepts section. Create a project space (directory structure) and populated it with the core code repository (apache-mynewt-core) or kn ow how to as explained in Creating Your First Project . Overview of Steps Install dependencies. Define the bootloader and Slinky application target for the target board. Build the bootloader target. Build the Slinky application target and create an application image. Set a up serial connection with the targets. Create a connection profile using the newtmgr tool. Use the newtmgr tool to communicate with the targets.","title":"toc"},{"location":"os/tutorials/project-slinky/#project-slinky","text":"The goal of the project is to use a sample application called \"Slinky\" included in the Mynewt repository to enable remote communications with a device running the Mynewt OS. The protocol for remote communications is called newt manager (newtmgr). If you have an existing project using a target that does not use the Slinky application and you wish to add newtmgr functionality to it, check out the tutorial titled Enable newtmgr in any app .","title":"Project Slinky"},{"location":"os/tutorials/project-slinky/#available-tutorials","text":"Tutorials are available for the following boards: Slinky on a simulated device . This is supported on Mac OS and Linux platforms. Slinky on a nRF52 . Slinky on an Olimex .","title":"Available Tutorials"},{"location":"os/tutorials/project-slinky/#prerequisites","text":"Ensure that you meet the following prerequisites before continuing with this tutorial: Have Internet connectivity to fetch remote Mynewt components. Have a computer to build a Mynewt application and connect to the board over USB. Have a Micro-USB cable to connect the board and the computer. Have a serial port setup . Install the newt tool and the toolchains (See Basic Setup ). Install the newtmgr tool . Read the Mynewt OS Concepts section. Create a project space (directory structure) and populated it with the core code repository (apache-mynewt-core) or kn ow how to as explained in Creating Your First Project .","title":"Prerequisites"},{"location":"os/tutorials/project-slinky/#overview-of-steps","text":"Install dependencies. Define the bootloader and Slinky application target for the target board. Build the bootloader target. Build the Slinky application target and create an application image. Set a up serial connection with the targets. Create a connection profile using the newtmgr tool. Use the newtmgr tool to communicate with the targets.","title":"Overview of Steps"},{"location":"os/tutorials/project-stm32-slinky/","text":"Project Slinky Using Olimex Board This tutorial shows you how to create, build and run the Slinky application and communicate with newtmgr for an Olimex STM-E407 board. Prerequisites Meet the prerequisites listed in Project Slinky . Have a STM32-E407 development board from Olimex. Have a ARM-USB-TINY-H connector with JTAG interface for debugging ARM microcontrollers (comes with the ribbon cable to hook up to the board) Have a USB A-B type cable to connect the debugger to your computer. Have a USB to TTL Serial Cable with female wiring harness. Install the OpenOCD debugger . Create a New Project Create a new project if you do not have an existing one. You can skip this step and proceed to create the targets if you already have a project created or completed the Sim Slinky tutorial. $ newt new slinky Downloading project skeleton from apache/incubator-mynewt-blinky... ... Installing skeleton in slink... Project slink successfully created $ cd slinky $newt install apache-mynewt-core Create the Targets Create two targets for the STM32-E407 board - one for the bootloader and one for the Slinky application. Run the following newt target commands, from your project directory, to create a bootloader target. We name the target stm32_boot . $ newt target create stm32_boot $ newt target set stm32_bootr bsp=@apache-mynewt-core/hw/bsp/olimex_stm32-e407_devboard $ newt target set stm32_boot build_profile=optimized $ newt target set stm32_boot target.app=@apache-mynewt-core/apps/boot Run the following newt target commands to create a target for the Slinky application. We name the target stm32_slinky . $ newt target create stm32_slinky $ newt target set stm32_slinky bsp=@apache-mynewt-core/hw/bsp/olimex_stm32-e407_devboard $ newt target set stm32_slinky build_profile=debug $ newt target set stm32_slinky app=@apache-mynewt-core/apps/slinky Build the Targets Run the newt build stm32_boot command to build the bootloader: $ newt build stm32_boot Building target targets/stm32_boot Compiling repos/apache-mynewt-core/boot/bootutil/src/image_ec256.c Compiling repos/apache-mynewt-core/boot/bootutil/src/image_rsa.c Compiling repos/apache-mynewt-core/boot/bootutil/src/loader.c Compiling repos/apache-mynewt-core/boot/bootutil/src/image_ec.c Compiling repos/apache-mynewt-core/boot/bootutil/src/image_validate.c Compiling repos/apache-mynewt-core/crypto/mbedtls/src/aes.c Compiling repos/apache-mynewt-core/boot/bootutil/src/bootutil_misc.c Compiling repos/apache-mynewt-core/apps/boot/src/boot.c ... Archiving sys_mfg.a Archiving sys_sysinit.a Archiving util_mem.a Linking ~/dev/slinky/bin/targets/stm32_boot/app/apps/boot/boot.elf Target successfully built: targets/stm32_boot $ Run the newt build stm32_slinky command to build the Slinky application: $newt build stm32_slinky Building target targets/stm32_slinky Compiling repos/apache-mynewt-core/boot/bootutil/src/image_ec.c Compiling repos/apache-mynewt-core/boot/bootutil/src/image_rsa.c Compiling repos/apache-mynewt-core/boot/bootutil/src/image_ec256.c Compiling repos/apache-mynewt-core/boot/bootutil/src/loader.c Compiling repos/apache-mynewt-core/boot/bootutil/src/image_validate.c Compiling repos/apache-mynewt-core/boot/split/src/split.c Compiling repos/apache-mynewt-core/boot/bootutil/src/bootutil_misc.c Compiling repos/apache-mynewt-core/apps/slinky/src/main.c ... Archiving util_crc.a Archiving util_mem.a Linking ~/dev/slinky/bin/targets/stm32_slinky/app/apps/slinky/slinky.elf Target successfully built: targets/stm32_slinky $ Sign and Create the Slinky Application Image Run the newt create-image stm32_slinky 1.0.0 command to create and sign the application image. You may assign an arbitrary version (e.g. 1.0.0) to the image. create-image stm32_slinky 1.0.0 App image succesfully generated: ~/dev/slinky/bin/targets/stm32_slinky/app/apps/slinky/slinky.img $ Connect to the Board Connect the USB A-B type cable to the ARM-USB-TINY-H debugger connector. Connect the ARM-USB-Tiny-H debugger connector to your computer and the board. Connect the USB Micro-A cable to the USB-OTG2 port on the board. Set the Power Sel jumper on the board to pins 5 and 6 to select USB-OTG2 as the power source. If you would like to use a different power source, refer to the OLIMEX STM32-E407 user manual for pin specifications. You should see a red LED light up on the board. Load the Bootloader and the Slinky Application Image Run the newt load stm32_boot command to load the bootloader onto the board: $ newt load stm32_boot Loading bootloader $ Note: If you are using Windows and get a no device found error, you will need to install the usb driver. Download Zadig and run it: Select Options > List All Devices. Select Olimex OpenOCD JTAG ARM-USB-TINY-H from the drop down menu. Select the WinUSB driver. Click Install Driver. Run the newt load stm32_boot command again. Run the newt load stm32_slinky command to load the Slinky application image onto the board: $ newt load stm32_slinky Loading app image into slot 1 $ Connect Newtmgr with the Board using a Serial Connection Locate the PC6/USART6_TX (pin 3), PC7/USART6_RX (pin 4), and GND (pin 2) of the UEXT connector on the Olimex board. More information on the UEXT connector can be found at https://www.olimex.com/Products/Modules/UEXT/ . The schematic of the board can be found at https://www.olimex.com/Products/ARM/ST/STM32-E407/resources/STM32-E407_sch.pdf for reference. Connect the female RX pin of the USB-TTL serial cable to the TX (Pin 3) of the UEXT connector on the board. Connect the female TX pin of the USB-TTL serial cable to the RX (Pin 4) of the UEXT connector on the board. Connect the GND pin of the USB-TTL serial cable to the GND (Pin 2) of the UEXT connector on the board. Locate the port, in the /dev directory on your computer, that the serial connection uses. The format of the port name is platform dependent: Mac OS uses the format tty.usbserial-<some identifier> . Linux uses the format TTYUSB<N> , where N is a number. For example, TTYUSB2. MinGW on Windows uses the format ttyS<N> , where N is a number. You must map the port name to a Windows COM port: /dev/ttyS<N> maps to COM<N+1> . For example, /dev/ttyS2 maps to COM3 . You can also use the Windows Device Manager to find the COM port number. $ ls /dev/tty*usbserial* /dev/tty.usbserial-1d13 $ Setup a newtmgr connection profile for the serial port. For our example, the port is /dev/tty.usbserial-1d13 . Run the newtmgr conn add command to define a newtmgr connection profile for the serial port. We name the connection profile stm32serial . Note : You will need to replace the connstring with the specific port for your serial connection. On Windows, you must specify COM<N+1> for the connstring if /dev/ttyS<N> is the serial port. $ newtmgr conn add stm32serial type=serial connstring=/dev/tty.usbserial-1d13 Connection profile stm32serial successfully added $ You can run the newt conn show command to see all the newtmgr connection profiles: $ newtmgr conn show Connection profiles: stm32serial: type=serial, connstring='/dev/tty.usbserial-1d13' sim1: type=serial, connstring='/dev/ttys012' $ Use Newtmgr to Query the Board Run some newtmgr commands to query and receive responses back from the board (See the Newt Manager Guide for more information on the newtmgr commands). Run the newtmgr echo hello -c stm32serial command. This is the simplest command that requests the board to echo back the text. $ newtmgr echo hello -c stm32serial hello $ Run the newtmgr image list -c stm32serial command to list the images on the board: $ newtmgr image list -c stm32serial Images: slot=0 version: 1.0.0 bootable: true flags: active confirmed hash: 9cf8af22b1b573909a8290a90c066d4e190407e97680b7a32243960ec2bf3a7f Split status: N/A $ Run the newtmgr taskstats -c stm32serial command to display the task statistics on the board: $ newtmgr taskstats -c stm32serial Return Code = 0 task pri tid runtime csw stksz stkuse last_checkin next_checkin task1 8 2 0 90 192 110 0 0 task2 9 3 0 90 64 31 0 0 idle 255 0 89460 89463 64 26 0 0 main 127 1 4 26 1024 368 0 0 $","title":"Slinky on Olimex"},{"location":"os/tutorials/project-stm32-slinky/#project-slinky-using-olimex-board","text":"This tutorial shows you how to create, build and run the Slinky application and communicate with newtmgr for an Olimex STM-E407 board.","title":"Project Slinky Using Olimex Board"},{"location":"os/tutorials/project-stm32-slinky/#prerequisites","text":"Meet the prerequisites listed in Project Slinky . Have a STM32-E407 development board from Olimex. Have a ARM-USB-TINY-H connector with JTAG interface for debugging ARM microcontrollers (comes with the ribbon cable to hook up to the board) Have a USB A-B type cable to connect the debugger to your computer. Have a USB to TTL Serial Cable with female wiring harness. Install the OpenOCD debugger .","title":"Prerequisites"},{"location":"os/tutorials/project-stm32-slinky/#create-a-new-project","text":"Create a new project if you do not have an existing one. You can skip this step and proceed to create the targets if you already have a project created or completed the Sim Slinky tutorial. $ newt new slinky Downloading project skeleton from apache/incubator-mynewt-blinky... ... Installing skeleton in slink... Project slink successfully created $ cd slinky $newt install apache-mynewt-core","title":"Create a New Project"},{"location":"os/tutorials/project-stm32-slinky/#create-the-targets","text":"Create two targets for the STM32-E407 board - one for the bootloader and one for the Slinky application. Run the following newt target commands, from your project directory, to create a bootloader target. We name the target stm32_boot . $ newt target create stm32_boot $ newt target set stm32_bootr bsp=@apache-mynewt-core/hw/bsp/olimex_stm32-e407_devboard $ newt target set stm32_boot build_profile=optimized $ newt target set stm32_boot target.app=@apache-mynewt-core/apps/boot Run the following newt target commands to create a target for the Slinky application. We name the target stm32_slinky . $ newt target create stm32_slinky $ newt target set stm32_slinky bsp=@apache-mynewt-core/hw/bsp/olimex_stm32-e407_devboard $ newt target set stm32_slinky build_profile=debug $ newt target set stm32_slinky app=@apache-mynewt-core/apps/slinky","title":" Create the Targets"},{"location":"os/tutorials/project-stm32-slinky/#build-the-targets","text":"Run the newt build stm32_boot command to build the bootloader: $ newt build stm32_boot Building target targets/stm32_boot Compiling repos/apache-mynewt-core/boot/bootutil/src/image_ec256.c Compiling repos/apache-mynewt-core/boot/bootutil/src/image_rsa.c Compiling repos/apache-mynewt-core/boot/bootutil/src/loader.c Compiling repos/apache-mynewt-core/boot/bootutil/src/image_ec.c Compiling repos/apache-mynewt-core/boot/bootutil/src/image_validate.c Compiling repos/apache-mynewt-core/crypto/mbedtls/src/aes.c Compiling repos/apache-mynewt-core/boot/bootutil/src/bootutil_misc.c Compiling repos/apache-mynewt-core/apps/boot/src/boot.c ... Archiving sys_mfg.a Archiving sys_sysinit.a Archiving util_mem.a Linking ~/dev/slinky/bin/targets/stm32_boot/app/apps/boot/boot.elf Target successfully built: targets/stm32_boot $ Run the newt build stm32_slinky command to build the Slinky application: $newt build stm32_slinky Building target targets/stm32_slinky Compiling repos/apache-mynewt-core/boot/bootutil/src/image_ec.c Compiling repos/apache-mynewt-core/boot/bootutil/src/image_rsa.c Compiling repos/apache-mynewt-core/boot/bootutil/src/image_ec256.c Compiling repos/apache-mynewt-core/boot/bootutil/src/loader.c Compiling repos/apache-mynewt-core/boot/bootutil/src/image_validate.c Compiling repos/apache-mynewt-core/boot/split/src/split.c Compiling repos/apache-mynewt-core/boot/bootutil/src/bootutil_misc.c Compiling repos/apache-mynewt-core/apps/slinky/src/main.c ... Archiving util_crc.a Archiving util_mem.a Linking ~/dev/slinky/bin/targets/stm32_slinky/app/apps/slinky/slinky.elf Target successfully built: targets/stm32_slinky $","title":"Build the Targets"},{"location":"os/tutorials/project-stm32-slinky/#sign-and-create-the-slinky-application-image","text":"Run the newt create-image stm32_slinky 1.0.0 command to create and sign the application image. You may assign an arbitrary version (e.g. 1.0.0) to the image. create-image stm32_slinky 1.0.0 App image succesfully generated: ~/dev/slinky/bin/targets/stm32_slinky/app/apps/slinky/slinky.img $","title":"Sign and Create the Slinky Application Image"},{"location":"os/tutorials/project-stm32-slinky/#connect-to-the-board","text":"Connect the USB A-B type cable to the ARM-USB-TINY-H debugger connector. Connect the ARM-USB-Tiny-H debugger connector to your computer and the board. Connect the USB Micro-A cable to the USB-OTG2 port on the board. Set the Power Sel jumper on the board to pins 5 and 6 to select USB-OTG2 as the power source. If you would like to use a different power source, refer to the OLIMEX STM32-E407 user manual for pin specifications. You should see a red LED light up on the board.","title":"Connect to the Board"},{"location":"os/tutorials/project-stm32-slinky/#load-the-bootloader-and-the-slinky-application-image","text":"Run the newt load stm32_boot command to load the bootloader onto the board: $ newt load stm32_boot Loading bootloader $ Note: If you are using Windows and get a no device found error, you will need to install the usb driver. Download Zadig and run it: Select Options > List All Devices. Select Olimex OpenOCD JTAG ARM-USB-TINY-H from the drop down menu. Select the WinUSB driver. Click Install Driver. Run the newt load stm32_boot command again. Run the newt load stm32_slinky command to load the Slinky application image onto the board: $ newt load stm32_slinky Loading app image into slot 1 $","title":"Load the Bootloader and the Slinky Application Image"},{"location":"os/tutorials/project-stm32-slinky/#connect-newtmgr-with-the-board-using-a-serial-connection","text":"Locate the PC6/USART6_TX (pin 3), PC7/USART6_RX (pin 4), and GND (pin 2) of the UEXT connector on the Olimex board. More information on the UEXT connector can be found at https://www.olimex.com/Products/Modules/UEXT/ . The schematic of the board can be found at https://www.olimex.com/Products/ARM/ST/STM32-E407/resources/STM32-E407_sch.pdf for reference. Connect the female RX pin of the USB-TTL serial cable to the TX (Pin 3) of the UEXT connector on the board. Connect the female TX pin of the USB-TTL serial cable to the RX (Pin 4) of the UEXT connector on the board. Connect the GND pin of the USB-TTL serial cable to the GND (Pin 2) of the UEXT connector on the board. Locate the port, in the /dev directory on your computer, that the serial connection uses. The format of the port name is platform dependent: Mac OS uses the format tty.usbserial-<some identifier> . Linux uses the format TTYUSB<N> , where N is a number. For example, TTYUSB2. MinGW on Windows uses the format ttyS<N> , where N is a number. You must map the port name to a Windows COM port: /dev/ttyS<N> maps to COM<N+1> . For example, /dev/ttyS2 maps to COM3 . You can also use the Windows Device Manager to find the COM port number. $ ls /dev/tty*usbserial* /dev/tty.usbserial-1d13 $ Setup a newtmgr connection profile for the serial port. For our example, the port is /dev/tty.usbserial-1d13 . Run the newtmgr conn add command to define a newtmgr connection profile for the serial port. We name the connection profile stm32serial . Note : You will need to replace the connstring with the specific port for your serial connection. On Windows, you must specify COM<N+1> for the connstring if /dev/ttyS<N> is the serial port. $ newtmgr conn add stm32serial type=serial connstring=/dev/tty.usbserial-1d13 Connection profile stm32serial successfully added $ You can run the newt conn show command to see all the newtmgr connection profiles: $ newtmgr conn show Connection profiles: stm32serial: type=serial, connstring='/dev/tty.usbserial-1d13' sim1: type=serial, connstring='/dev/ttys012' $","title":"Connect Newtmgr with the Board using a Serial Connection"},{"location":"os/tutorials/project-stm32-slinky/#use-newtmgr-to-query-the-board","text":"Run some newtmgr commands to query and receive responses back from the board (See the Newt Manager Guide for more information on the newtmgr commands). Run the newtmgr echo hello -c stm32serial command. This is the simplest command that requests the board to echo back the text. $ newtmgr echo hello -c stm32serial hello $ Run the newtmgr image list -c stm32serial command to list the images on the board: $ newtmgr image list -c stm32serial Images: slot=0 version: 1.0.0 bootable: true flags: active confirmed hash: 9cf8af22b1b573909a8290a90c066d4e190407e97680b7a32243960ec2bf3a7f Split status: N/A $ Run the newtmgr taskstats -c stm32serial command to display the task statistics on the board: $ newtmgr taskstats -c stm32serial Return Code = 0 task pri tid runtime csw stksz stkuse last_checkin next_checkin task1 8 2 0 90 192 110 0 0 task2 9 3 0 90 64 31 0 0 idle 255 0 89460 89463 64 26 0 0 main 127 1 4 26 1024 368 0 0 $","title":"Use Newtmgr to Query the Board"},{"location":"os/tutorials/rbnano2/","text":"Blinky, your \"Hello World!\", on RedBear Nano 2 This tutorial shows you how to create, build and run the Blinky application on a RedBear Nano 2 board. Prerequisites Meet the prerequisites listed in Project Blinky . Have a RedBear Nano 2 board. Install a patched version of OpenOCD 0.10.0 described in Install OpenOCD . Create a Project Create a new project if you do not have an existing one. You can skip this step and proceed to create the targets if you already have a project created. Run the following commands to create a new project: $ mkdir ~/dev $ cd ~/dev $ newt new myproj Downloading project skeleton from apache/incubator-mynewt-blinky... Installing skeleton in myproj... Project myproj successfully created. $ cd myproj $ newt install apache-mynewt-core $ Create the Targets Create two targets for the RedBear Nano 2 board - one for the bootloader and one for the Blinky application. Run the following newt target commands, from your project directory, to create a bootloader target. We name the target rbnano2_boot : $ newt target create rbnano2_boot $ newt target set rbnano2_boot app=@apache-mynewt-core/apps/boot $ newt target set rbnano2_boot bsp=@apache-mynewt-core/hw/bsp/rb-nano2 $ newt target set rbnano2_boot build_profile=optimized Run the following newt target commands to create a target for the Blinky application. We name the target nrf52_blinky . $ newt target create rbnano2_blinky $ newt target set rbnano2_blinky app=apps/blinky $ newt target set rbnano2_blinky bsp=@apache-mynewt-core/hw/bsp/rb-nano2 $ newt target set rbnano2_blinky build_profile=debug You can run the newt target show command to verify the target settings: $ newt target show targets/rbnano2_blinky app=apps/blinky bsp=@apache-mynewt-core/hw/bsp/rb-nano2 build_profile=debug targets/rbnano2_boot app=@apache-mynewt-core/apps/boot bsp=@apache-mynewt-core/hw/bsp/rb-nano2 build_profile=optimized Build the Target Executables Run the newt build rbnano2_boot command to build the bootloader: $newt build rbnano2_boot Building target targets/rbnano2_boot Compiling repos/apache-mynewt-core/boot/bootutil/src/image_rsa.c Compiling repos/apache-mynewt-core/boot/bootutil/src/image_ec256.c Compiling repos/apache-mynewt-core/boot/bootutil/src/loader.c Compiling repos/apache-mynewt-core/crypto/mbedtls/src/aes.c Compiling repos/apache-mynewt-core/boot/bootutil/src/image_validate.c Compiling repos/apache-mynewt-core/boot/bootutil/src/image_ec.c Compiling repos/apache-mynewt-core/boot/bootutil/src/bootutil_misc.c Compiling repos/apache-mynewt-core/apps/boot/src/boot.c ... Archiving sys_sysinit.a Archiving util_mem.a Linking ~/dev/myproj/bin/targets/rbnano2_boot/app/apps/boot/boot.elf Target successfully built: targets/rbnano2_boot Run the newt build rbnano2_blinky command to build the Blinky application: $newt build rbnano2_blinky Building target targets/rbnano2_blinky Assembling repos/apache-mynewt-core/hw/bsp/rb-nano2/src/arch/cortex_m4/gcc_startup_nrf52_split.s Compiling repos/apache-mynewt-core/hw/drivers/uart/src/uart.c Compiling repos/apache-mynewt-core/hw/cmsis-core/src/cmsis_nvic.c Compiling repos/apache-mynewt-core/hw/bsp/rb-nano2/src/sbrk.c Compiling apps/blinky/src/main.c ... Archiving sys_sysinit.a Archiving util_mem.a Linking ~/dev/myproj/bin/targets/rbnano2_blinky/app/apps/blinky/blinky.elf Target successfully built: targets/rbnano2_blinky Sign and Create the Blinky Application Image Run the newt create-image rbnano2_blinky 1.0.0 command to create and sign the application image. You may assign an arbitrary version (e.g. 1.0.0) to the image. $newt create-image rbnano2_blinky 1.0.0 App image succesfully generated: ~/dev/myproj/bin/targets/rbnano2_blinky/app/apps/blinky/blinky.img Connect to the Board Connect the RedBear Nano 2 USB to a USB port on your computer. You should see an orange LED light up on the board. Load the Bootloader Run the newt load rbnano2_boot command to load the bootloader onto the board: $ newt load rbnano2_boot Loading bootloader $ Note: On Windows platforms, if you get an unable to find CMSIS-DAP device error, you will need to download and install the mbed Windows serial port driver from https://developer.mbed.org/handbook/Windows-serial-configuration . Follow the instructions from the site to install the driver. Here are some additional notes about the installation: The instructions indicate that the mbed Windows serial port driver is not required for Windows 10. If you are using Windows 10 and get the unable to find CMSIS-DAP device error, we recommend that you install the driver. If the driver installation fails, we recommend that you unplug the board, plug it back in, and retry the installation. Run the newt load rbnano2_boot command again. Clear the Write Protection on the Flash Memory The flash memory on the RedBear Nano 2 comes write protected from the factory. If you get an error loading the bootloader and you are using a brand new chip, you need to clear the write protection from the debugger and then load the bootloader again. Run the newt debug rbnano2_blinky command and issue the following commands at the highlighted (gdb) prompts. Note: The output of the debug session below is for Mac OS and Linux platforms. On Windows, openocd and gdb are started in separate Windows Command Prompt terminals, and the terminals are automatically closed when you quit gdb. In addition, the output of openocd is logged to the openocd.log file in your project's base directory instead of the terminal. $newt debug rbnano2_blinky [~/dev/myproj/repos/apache-mynewt-core/hw/bsp/rb-nano2/rb-nano2_debug.sh ~/dev/myproj/repos/apache-mynewt-core/hw/bsp/rb-nano2 ~/dev/myproj/bin/targets/rbnano2_blinky/app/apps/blinky/blinky] Open On-Chip Debugger 0.10.0-dev-snapshot (2017-03-28-11:24) Licensed under GNU GPL v2 ... (gdb) set {unsigned long}0x4001e504=2 (gdb) x/1wx 0x4001e504 0x4001e504:0x00000002 (gdb) set {unsigned long}0x4001e50c=1 Info : SWD DPIDR 0x2ba01477 Error: Failed to read memory at 0x00009ef4 (gdb) x/32wx 0x00 0x0:0xffffffff0xffffffff0xffffffff0xffffffff 0x10:0xffffffff0xffffffff0xffffffff0xffffffff 0x20:0xffffffff0xffffffff0xffffffff0xffffffff 0x30:0xffffffff0xffffffff0xffffffff0xffffffff 0x40:0xffffffff0xffffffff0xffffffff0xffffffff 0x50:0xffffffff0xffffffff0xffffffff0xffffffff 0x60:0xffffffff0xffffffff0xffffffff0xffffffff 0x70:0xffffffff0xffffffff0xffffffff0xffffffff (gdb) Load the Blinky Application Image Run the newt load rbnano2_blinky command to load the Blinky application image onto the board: $ newt load rbnano2_blinky Loading app image into slot 1 You should see a blue LED on the board blink! Note: If the LED does not blink, try resetting your board.","title":"Blinky on RedBear Nano 2"},{"location":"os/tutorials/rbnano2/#blinky-your-hello-world-on-redbear-nano-2","text":"This tutorial shows you how to create, build and run the Blinky application on a RedBear Nano 2 board.","title":"Blinky, your \"Hello World!\", on RedBear Nano 2"},{"location":"os/tutorials/rbnano2/#prerequisites","text":"Meet the prerequisites listed in Project Blinky . Have a RedBear Nano 2 board. Install a patched version of OpenOCD 0.10.0 described in Install OpenOCD .","title":"Prerequisites"},{"location":"os/tutorials/rbnano2/#create-a-project","text":"Create a new project if you do not have an existing one. You can skip this step and proceed to create the targets if you already have a project created. Run the following commands to create a new project: $ mkdir ~/dev $ cd ~/dev $ newt new myproj Downloading project skeleton from apache/incubator-mynewt-blinky... Installing skeleton in myproj... Project myproj successfully created. $ cd myproj $ newt install apache-mynewt-core $","title":"Create a Project"},{"location":"os/tutorials/rbnano2/#create-the-targets","text":"Create two targets for the RedBear Nano 2 board - one for the bootloader and one for the Blinky application. Run the following newt target commands, from your project directory, to create a bootloader target. We name the target rbnano2_boot : $ newt target create rbnano2_boot $ newt target set rbnano2_boot app=@apache-mynewt-core/apps/boot $ newt target set rbnano2_boot bsp=@apache-mynewt-core/hw/bsp/rb-nano2 $ newt target set rbnano2_boot build_profile=optimized Run the following newt target commands to create a target for the Blinky application. We name the target nrf52_blinky . $ newt target create rbnano2_blinky $ newt target set rbnano2_blinky app=apps/blinky $ newt target set rbnano2_blinky bsp=@apache-mynewt-core/hw/bsp/rb-nano2 $ newt target set rbnano2_blinky build_profile=debug You can run the newt target show command to verify the target settings: $ newt target show targets/rbnano2_blinky app=apps/blinky bsp=@apache-mynewt-core/hw/bsp/rb-nano2 build_profile=debug targets/rbnano2_boot app=@apache-mynewt-core/apps/boot bsp=@apache-mynewt-core/hw/bsp/rb-nano2 build_profile=optimized","title":"Create the Targets"},{"location":"os/tutorials/rbnano2/#build-the-target-executables","text":"Run the newt build rbnano2_boot command to build the bootloader: $newt build rbnano2_boot Building target targets/rbnano2_boot Compiling repos/apache-mynewt-core/boot/bootutil/src/image_rsa.c Compiling repos/apache-mynewt-core/boot/bootutil/src/image_ec256.c Compiling repos/apache-mynewt-core/boot/bootutil/src/loader.c Compiling repos/apache-mynewt-core/crypto/mbedtls/src/aes.c Compiling repos/apache-mynewt-core/boot/bootutil/src/image_validate.c Compiling repos/apache-mynewt-core/boot/bootutil/src/image_ec.c Compiling repos/apache-mynewt-core/boot/bootutil/src/bootutil_misc.c Compiling repos/apache-mynewt-core/apps/boot/src/boot.c ... Archiving sys_sysinit.a Archiving util_mem.a Linking ~/dev/myproj/bin/targets/rbnano2_boot/app/apps/boot/boot.elf Target successfully built: targets/rbnano2_boot Run the newt build rbnano2_blinky command to build the Blinky application: $newt build rbnano2_blinky Building target targets/rbnano2_blinky Assembling repos/apache-mynewt-core/hw/bsp/rb-nano2/src/arch/cortex_m4/gcc_startup_nrf52_split.s Compiling repos/apache-mynewt-core/hw/drivers/uart/src/uart.c Compiling repos/apache-mynewt-core/hw/cmsis-core/src/cmsis_nvic.c Compiling repos/apache-mynewt-core/hw/bsp/rb-nano2/src/sbrk.c Compiling apps/blinky/src/main.c ... Archiving sys_sysinit.a Archiving util_mem.a Linking ~/dev/myproj/bin/targets/rbnano2_blinky/app/apps/blinky/blinky.elf Target successfully built: targets/rbnano2_blinky","title":"Build the Target Executables"},{"location":"os/tutorials/rbnano2/#sign-and-create-the-blinky-application-image","text":"Run the newt create-image rbnano2_blinky 1.0.0 command to create and sign the application image. You may assign an arbitrary version (e.g. 1.0.0) to the image. $newt create-image rbnano2_blinky 1.0.0 App image succesfully generated: ~/dev/myproj/bin/targets/rbnano2_blinky/app/apps/blinky/blinky.img","title":"Sign and Create the Blinky Application Image"},{"location":"os/tutorials/rbnano2/#connect-to-the-board","text":"Connect the RedBear Nano 2 USB to a USB port on your computer. You should see an orange LED light up on the board.","title":"Connect to the Board"},{"location":"os/tutorials/rbnano2/#load-the-bootloader","text":"Run the newt load rbnano2_boot command to load the bootloader onto the board: $ newt load rbnano2_boot Loading bootloader $ Note: On Windows platforms, if you get an unable to find CMSIS-DAP device error, you will need to download and install the mbed Windows serial port driver from https://developer.mbed.org/handbook/Windows-serial-configuration . Follow the instructions from the site to install the driver. Here are some additional notes about the installation: The instructions indicate that the mbed Windows serial port driver is not required for Windows 10. If you are using Windows 10 and get the unable to find CMSIS-DAP device error, we recommend that you install the driver. If the driver installation fails, we recommend that you unplug the board, plug it back in, and retry the installation. Run the newt load rbnano2_boot command again.","title":"Load the Bootloader"},{"location":"os/tutorials/rbnano2/#clear-the-write-protection-on-the-flash-memory","text":"The flash memory on the RedBear Nano 2 comes write protected from the factory. If you get an error loading the bootloader and you are using a brand new chip, you need to clear the write protection from the debugger and then load the bootloader again. Run the newt debug rbnano2_blinky command and issue the following commands at the highlighted (gdb) prompts. Note: The output of the debug session below is for Mac OS and Linux platforms. On Windows, openocd and gdb are started in separate Windows Command Prompt terminals, and the terminals are automatically closed when you quit gdb. In addition, the output of openocd is logged to the openocd.log file in your project's base directory instead of the terminal. $newt debug rbnano2_blinky [~/dev/myproj/repos/apache-mynewt-core/hw/bsp/rb-nano2/rb-nano2_debug.sh ~/dev/myproj/repos/apache-mynewt-core/hw/bsp/rb-nano2 ~/dev/myproj/bin/targets/rbnano2_blinky/app/apps/blinky/blinky] Open On-Chip Debugger 0.10.0-dev-snapshot (2017-03-28-11:24) Licensed under GNU GPL v2 ... (gdb) set {unsigned long}0x4001e504=2 (gdb) x/1wx 0x4001e504 0x4001e504:0x00000002 (gdb) set {unsigned long}0x4001e50c=1 Info : SWD DPIDR 0x2ba01477 Error: Failed to read memory at 0x00009ef4 (gdb) x/32wx 0x00 0x0:0xffffffff0xffffffff0xffffffff0xffffffff 0x10:0xffffffff0xffffffff0xffffffff0xffffffff 0x20:0xffffffff0xffffffff0xffffffff0xffffffff 0x30:0xffffffff0xffffffff0xffffffff0xffffffff 0x40:0xffffffff0xffffffff0xffffffff0xffffffff 0x50:0xffffffff0xffffffff0xffffffff0xffffffff 0x60:0xffffffff0xffffffff0xffffffff0xffffffff 0x70:0xffffffff0xffffffff0xffffffff0xffffffff (gdb)","title":"Clear the Write Protection on the Flash Memory"},{"location":"os/tutorials/rbnano2/#load-the-blinky-application-image","text":"Run the newt load rbnano2_blinky command to load the Blinky application image onto the board: $ newt load rbnano2_blinky Loading app image into slot 1 You should see a blue LED on the board blink! Note: If the LED does not blink, try resetting your board.","title":"Load the Blinky Application Image"},{"location":"os/tutorials/tasks_lesson/","text":"Tasks and Priority Management Target Platform: Arduino M0 Pro (or legacy Arduino Zero or Zero Pro, but not Arduino M0) This lesson is designed to teach core OS concepts and strategies encountered when building applications using Mynewt. Specifically, this lesson will cover tasks, simple multitasking, and priority management running on an Arduino M0 Pro. Prerequisites Before starting, you should read about Mynewt in the Introduction section and complete the QuickStart guide and the Blinky tutorial. Furthermore, it may be helpful to take a peek at the task documentation for additional insights. Equipment You will need the following equipment: Arduino M0 Pro (or legacy Arduino Zero or Zero Pro, but not Arduino M0) Computer with Mynewt installed USB to Micro USB Cable Build Your Application To save time, we will simply modify the Blinky application. We'll add the Task Management code to the Blinky application. Follow the Arduino Zero Blinky tutorial to create a new project and build your bootloader and application. Finally, build and load the application to your Arduino to verify that everything is in order. Now let\u2019s get started! Default Main Task During Mynewt system startup, Mynewt creates a default main task and executes the application main() function in the context of this task. The main task priority defaults to 127 and can be configured with the OS_MAIN_TASK_PRIO system configuration setting. The blinky application only has the main task. The main() function executes an infinite loop that toggles the led and sleeps for one second. Create a New Task The purpose of this section is to give an introduction to the important aspects of tasks and how to properly initialize them. First, let\u2019s define a second task called work_task in main.c (located in apps/blinky/src): struct os_task work_task ; A task is represented by the os_task struct which will hold the task\u2019s information (name, state, priority, etc.). A task is made up of two main elements, a task function (also known as a task handler) and a task stack. Next, let\u2019s take a look at what is required to initialize our new task. Task Stack The task stack is an array of type os_stack_t which holds the program stack frames. Mynewt gives us the ability to set the stack size for a task giving the application developer room to optimize memory usage. Since we\u2019re not short on memory, our work_stack is plenty large for the purpose of this lesson. Notice that the elements in our task stack are of type os_stack_t which are generally 32 bits, making our entire stack 1024 Bytes. #define WORK_STACK_SIZE OS_STACK_ALIGN(256) Note: The OS_STACK_ALIGN macro is used to align the stack based on the hardware architecture. Task Function A task function is essentially an infinite loop that waits for some \u201cevent\u201d to wake it up. In general, the task function is where the majority of work is done by a task. Let\u2019s write a task function for work_task called work_task_handler() : void work_task_handler ( void *arg ) { struct os_task *t ; g_led_pin = LED_BLINK_PIN ; hal_gpio_init_out ( g_led_pin , 1 ); while ( 1 ) { t = os_sched_get_current_task (); assert ( t->t_func == work_task_handler ); /* Do work... */ } } The task function is called when the task is initially put into the running state by the scheduler. We use an infinite loop to ensure that the task function never returns. Our assertion that the current task's handler is the same as our task handler is for illustration purposes only and does not need to be in most task functions. Task Priority As a preemptive, multitasking RTOS, Mynewt decides which tasks to run based on which has a higher priority; the highest priority being 0 and the lowest 255. Thus, before initializing our task, we must choose a priority defined as a macro variable. Let\u2019s set the priority of work_task to 0, because everyone knows that work is more important than blinking. #define WORK_TASK_PRIO (0) Initialization To initialize a new task we use os_task_init() which takes a number of arguments including our new task function, stack, and priority. Add the init_tasks() function to initialize work_task to keep our main function clean. int init_tasks ( void ) { /* \u2026 */ os_stack_t *work_stack ; work_stack = malloc ( sizeof ( os_stack_t ) *WORK_STACK_SIZE ); assert ( work_stack ); os_task_init ( &work_task , \"work\" , work_task_handler , NULL , WORK_TASK_PRIO , OS_WAIT_FOREVER , work_stack , WORK_STACK_SIZE ); return 0 ; } Add the call to init_tasks() in main() before the while loop: int main ( int argc , char **argv ) { ... /* Initialize the work task */ init_tasks (); while ( 1 ) { ... } } And that\u2019s it! Now run your application using the newt run command. $ newt run arduino_blinky 0.0.0 When GDB appears press C then Enter to continue and \u2026 wait, why doesn't our LED blink anymore? Review Before we run our new app, let\u2019s review what we need in order to create a task. This is a general case for a new task called mytask: 1) Define a new task, task stack, and priority: /* My Task */ struct os_task mytask /* My Task Stack */ #define MYTASK_STACK_SIZE OS_STACK_ALIGN(256) os_stack_t mytask_stack [ MYTASK_STACK_SIZE ]; /* My Task Priority */ #define MYTASK_PRIO (0) 2) Define task function: void mytask_handler ( void *arg ) { while ( 1 ) { /* ... */ } } 3) Initialize the task: os_task_init ( &mytask , \"mytask\" , mytask_handler , NULL , MYTASK_PRIO , OS_WAIT_FOREVER , mytask_stack , MYTASK_STACK_SIZE ); Task Priority, Preempting, and Context Switching A preemptive RTOS is one in which a higher priority task that is ready to run will preempt (i.e. take the place of) the lower priority task which is running . When a lower priority task is preempted by a higher priority task, the lower priority task\u2019s context data (stack pointer, registers, etc.) is saved and the new task is switched in. In our example, work_task (priority 0) has a higher priority than the main task (priority 127). Since work_task is never put into a sleep state, it holds the processor focus on its context. Let\u2019s give work_task a delay and some simulated work to keep it busy. The delay is measured in os ticks and the actual number of ticks per second is dependent on the board. We multiply OS_TICKS_PER_SEC , which is defined in the MCU, by the number of seconds we wish to delay. void work_task_handler ( void *arg ) { struct os_task *t ; g_led_pin = LED_BLINK_PIN ; hal_gpio_init_out ( g_led_pin , 1 ); while ( 1 ) { t = os_sched_get_current_t:ask (); assert ( t->t_func == work_task_handler ); /* Do work... */ int i ; for ( i = 0 ; i < 1000000 ; ++i ) { /* Simulate doing a noticeable amount of work */ hal_gpio_write ( g_led_pin , 1 ); } os_time_delay ( 3 * OS_TICKS_PER_SEC ); } } In order to notice the LED changing, modify the time delay in main() to blink at a higher frequency. os_time_delay ( OS_TICKS_PER_SEC/ 10 ); Before we run the app, let\u2019s predict the behavior. With the newest additions to work_task_handler() , our first action will be to sleep for three seconds. This allows the main task, running main() , to take over the CPU and blink to its heart\u2019s content. After three seconds, work_task will wake up and be made ready to run . This causes it to preempt the main task. The LED will then remain lit for a short period while work_task loops, then blink again for another three seconds while work_task sleeps. You should see that our prediction was correct! Priority Management Considerations When projects grow in scope, from blinking LEDs into more sophisticated applications, the number of tasks needed increases alongside complexity. It remains important, then, that each of our tasks is capable of doing its work within a reasonable amount of time. Some tasks, such as the Shell task, execute quickly and require almost instantaneous response. Therefore, the Shell task should be given a high priority. On the other hand, tasks which may be communicating over a network, or processing data, should be given a low priority in order to not hog the CPU. The diagram below shows the different scheduling patterns we would expect when we set the work_task priority higher and lower than the main task priority. In the second case where the main task has a higher priority, work_task runs and executes \u201cwork\u201d when the main task sleeps, saving us idle time compared to the first case. Note: Defining the same priority for two tasks leads to somewhat undefined behavior and should be avoided.","title":"Tasks and Priority Management"},{"location":"os/tutorials/tasks_lesson/#tasks-and-priority-management","text":"Target Platform: Arduino M0 Pro (or legacy Arduino Zero or Zero Pro, but not Arduino M0) This lesson is designed to teach core OS concepts and strategies encountered when building applications using Mynewt. Specifically, this lesson will cover tasks, simple multitasking, and priority management running on an Arduino M0 Pro.","title":"Tasks and Priority Management"},{"location":"os/tutorials/tasks_lesson/#prerequisites","text":"Before starting, you should read about Mynewt in the Introduction section and complete the QuickStart guide and the Blinky tutorial. Furthermore, it may be helpful to take a peek at the task documentation for additional insights.","title":"Prerequisites"},{"location":"os/tutorials/tasks_lesson/#equipment","text":"You will need the following equipment: Arduino M0 Pro (or legacy Arduino Zero or Zero Pro, but not Arduino M0) Computer with Mynewt installed USB to Micro USB Cable","title":"Equipment"},{"location":"os/tutorials/tasks_lesson/#build-your-application","text":"To save time, we will simply modify the Blinky application. We'll add the Task Management code to the Blinky application. Follow the Arduino Zero Blinky tutorial to create a new project and build your bootloader and application. Finally, build and load the application to your Arduino to verify that everything is in order. Now let\u2019s get started!","title":"Build Your Application"},{"location":"os/tutorials/tasks_lesson/#default-main-task","text":"During Mynewt system startup, Mynewt creates a default main task and executes the application main() function in the context of this task. The main task priority defaults to 127 and can be configured with the OS_MAIN_TASK_PRIO system configuration setting. The blinky application only has the main task. The main() function executes an infinite loop that toggles the led and sleeps for one second.","title":"Default Main Task"},{"location":"os/tutorials/tasks_lesson/#create-a-new-task","text":"The purpose of this section is to give an introduction to the important aspects of tasks and how to properly initialize them. First, let\u2019s define a second task called work_task in main.c (located in apps/blinky/src): struct os_task work_task ; A task is represented by the os_task struct which will hold the task\u2019s information (name, state, priority, etc.). A task is made up of two main elements, a task function (also known as a task handler) and a task stack. Next, let\u2019s take a look at what is required to initialize our new task.","title":"Create a New Task"},{"location":"os/tutorials/tasks_lesson/#task-stack","text":"The task stack is an array of type os_stack_t which holds the program stack frames. Mynewt gives us the ability to set the stack size for a task giving the application developer room to optimize memory usage. Since we\u2019re not short on memory, our work_stack is plenty large for the purpose of this lesson. Notice that the elements in our task stack are of type os_stack_t which are generally 32 bits, making our entire stack 1024 Bytes. #define WORK_STACK_SIZE OS_STACK_ALIGN(256) Note: The OS_STACK_ALIGN macro is used to align the stack based on the hardware architecture.","title":"Task Stack"},{"location":"os/tutorials/tasks_lesson/#task-function","text":"A task function is essentially an infinite loop that waits for some \u201cevent\u201d to wake it up. In general, the task function is where the majority of work is done by a task. Let\u2019s write a task function for work_task called work_task_handler() : void work_task_handler ( void *arg ) { struct os_task *t ; g_led_pin = LED_BLINK_PIN ; hal_gpio_init_out ( g_led_pin , 1 ); while ( 1 ) { t = os_sched_get_current_task (); assert ( t->t_func == work_task_handler ); /* Do work... */ } } The task function is called when the task is initially put into the running state by the scheduler. We use an infinite loop to ensure that the task function never returns. Our assertion that the current task's handler is the same as our task handler is for illustration purposes only and does not need to be in most task functions.","title":"Task Function"},{"location":"os/tutorials/tasks_lesson/#task-priority","text":"As a preemptive, multitasking RTOS, Mynewt decides which tasks to run based on which has a higher priority; the highest priority being 0 and the lowest 255. Thus, before initializing our task, we must choose a priority defined as a macro variable. Let\u2019s set the priority of work_task to 0, because everyone knows that work is more important than blinking. #define WORK_TASK_PRIO (0)","title":"Task Priority"},{"location":"os/tutorials/tasks_lesson/#initialization","text":"To initialize a new task we use os_task_init() which takes a number of arguments including our new task function, stack, and priority. Add the init_tasks() function to initialize work_task to keep our main function clean. int init_tasks ( void ) { /* \u2026 */ os_stack_t *work_stack ; work_stack = malloc ( sizeof ( os_stack_t ) *WORK_STACK_SIZE ); assert ( work_stack ); os_task_init ( &work_task , \"work\" , work_task_handler , NULL , WORK_TASK_PRIO , OS_WAIT_FOREVER , work_stack , WORK_STACK_SIZE ); return 0 ; } Add the call to init_tasks() in main() before the while loop: int main ( int argc , char **argv ) { ... /* Initialize the work task */ init_tasks (); while ( 1 ) { ... } } And that\u2019s it! Now run your application using the newt run command. $ newt run arduino_blinky 0.0.0 When GDB appears press C then Enter to continue and \u2026 wait, why doesn't our LED blink anymore?","title":"Initialization"},{"location":"os/tutorials/tasks_lesson/#review","text":"Before we run our new app, let\u2019s review what we need in order to create a task. This is a general case for a new task called mytask: 1) Define a new task, task stack, and priority: /* My Task */ struct os_task mytask /* My Task Stack */ #define MYTASK_STACK_SIZE OS_STACK_ALIGN(256) os_stack_t mytask_stack [ MYTASK_STACK_SIZE ]; /* My Task Priority */ #define MYTASK_PRIO (0) 2) Define task function: void mytask_handler ( void *arg ) { while ( 1 ) { /* ... */ } } 3) Initialize the task: os_task_init ( &mytask , \"mytask\" , mytask_handler , NULL , MYTASK_PRIO , OS_WAIT_FOREVER , mytask_stack , MYTASK_STACK_SIZE );","title":"Review"},{"location":"os/tutorials/tasks_lesson/#task-priority-preempting-and-context-switching","text":"A preemptive RTOS is one in which a higher priority task that is ready to run will preempt (i.e. take the place of) the lower priority task which is running . When a lower priority task is preempted by a higher priority task, the lower priority task\u2019s context data (stack pointer, registers, etc.) is saved and the new task is switched in. In our example, work_task (priority 0) has a higher priority than the main task (priority 127). Since work_task is never put into a sleep state, it holds the processor focus on its context. Let\u2019s give work_task a delay and some simulated work to keep it busy. The delay is measured in os ticks and the actual number of ticks per second is dependent on the board. We multiply OS_TICKS_PER_SEC , which is defined in the MCU, by the number of seconds we wish to delay. void work_task_handler ( void *arg ) { struct os_task *t ; g_led_pin = LED_BLINK_PIN ; hal_gpio_init_out ( g_led_pin , 1 ); while ( 1 ) { t = os_sched_get_current_t:ask (); assert ( t->t_func == work_task_handler ); /* Do work... */ int i ; for ( i = 0 ; i < 1000000 ; ++i ) { /* Simulate doing a noticeable amount of work */ hal_gpio_write ( g_led_pin , 1 ); } os_time_delay ( 3 * OS_TICKS_PER_SEC ); } } In order to notice the LED changing, modify the time delay in main() to blink at a higher frequency. os_time_delay ( OS_TICKS_PER_SEC/ 10 ); Before we run the app, let\u2019s predict the behavior. With the newest additions to work_task_handler() , our first action will be to sleep for three seconds. This allows the main task, running main() , to take over the CPU and blink to its heart\u2019s content. After three seconds, work_task will wake up and be made ready to run . This causes it to preempt the main task. The LED will then remain lit for a short period while work_task loops, then blink again for another three seconds while work_task sleeps. You should see that our prediction was correct!","title":"Task Priority, Preempting, and Context Switching"},{"location":"os/tutorials/tasks_lesson/#priority-management-considerations","text":"When projects grow in scope, from blinking LEDs into more sophisticated applications, the number of tasks needed increases alongside complexity. It remains important, then, that each of our tasks is capable of doing its work within a reasonable amount of time. Some tasks, such as the Shell task, execute quickly and require almost instantaneous response. Therefore, the Shell task should be given a high priority. On the other hand, tasks which may be communicating over a network, or processing data, should be given a low priority in order to not hog the CPU. The diagram below shows the different scheduling patterns we would expect when we set the work_task priority higher and lower than the main task priority. In the second case where the main task has a higher priority, work_task runs and executes \u201cwork\u201d when the main task sleeps, saving us idle time compared to the first case. Note: Defining the same priority for two tasks leads to somewhat undefined behavior and should be avoided.","title":"Priority Management Considerations"},{"location":"os/tutorials/try_markdown/","text":"Try Markdown Heading3 Heading4 List Start with one # for the largest heading (Heading1). The next smaller heading (Heading2) starts with ##. You can go all the way up to Heading 6 (######). Heading4 (####) and Heading5 (#####) has been styled to show up underlined. Yes, it can be changed. If you are curious, you can look at the extra.css file in your repo branch. It's very easy to do bold and italics . See how this list has been made using * Click on \"Help\" in Mou and then on \"Markdown Syntax Reference\". Substitute a sentence of your own here Guinea Pig!!! Note! You will not be able to see the change immediately by refreshing your browser right after editign the Markdown file. You can only push the change to the Apache repository. So continue with the steps in how_to_edit_docs.md . You can see the change on the website if/when a doc builder on the project team merges your changes to the master branch and generates the pages for the website. You do have the option to download MkDocs and preview the change by hosting the pages locally using its built-in web server. The steps are described in how_to_edit_docs.md .","title":"Try markdown"},{"location":"os/tutorials/try_markdown/#try-markdown","text":"","title":"Try Markdown"},{"location":"os/tutorials/try_markdown/#heading3","text":"","title":"Heading3"},{"location":"os/tutorials/try_markdown/#heading4","text":"","title":"Heading4"},{"location":"os/tutorials/try_markdown/#list","text":"Start with one # for the largest heading (Heading1). The next smaller heading (Heading2) starts with ##. You can go all the way up to Heading 6 (######). Heading4 (####) and Heading5 (#####) has been styled to show up underlined. Yes, it can be changed. If you are curious, you can look at the extra.css file in your repo branch. It's very easy to do bold and italics . See how this list has been made using * Click on \"Help\" in Mou and then on \"Markdown Syntax Reference\". Substitute a sentence of your own here Guinea Pig!!! Note! You will not be able to see the change immediately by refreshing your browser right after editign the Markdown file. You can only push the change to the Apache repository. So continue with the steps in how_to_edit_docs.md . You can see the change on the website if/when a doc builder on the project team merges your changes to the master branch and generates the pages for the website. You do have the option to download MkDocs and preview the change by hosting the pages locally using its built-in web server. The steps are described in how_to_edit_docs.md .","title":"List"},{"location":"os/tutorials/tutorials/","text":"Tutorials If the introduction to Mynewt has piqued your interest and you want to familiarize yourself with some of its functionality, this series of tutorials is for you. The lessons are aimed at the beginner. The full list of tutorials can be seen in the navigation bar on the left. New ones are being constantly added and will show up there automatically. Prerequisites: You have installed Docker container of Newt tool and toolchains or you have installed them natively on your machine You have created a new project space (directory structure) and populated it with the core code repository (apache-mynewt-core) or know how to as explained in Creating Your First Project . You have at least one of the supported development boards: Arduino Zero hardware Olimex/STM32F407ZGT6 Cortex-M4 hardware nRF52 Development Kit from Nordic Semiconductor The Nordic nrf52 developer kit supports Bluetooth Low Energy. We are always looking to add new hardware to the list, so if you want to develop the required Board Support Package (bsp) and/or Hardware Abstraction Layer (HAL) for a new board, you can look here to get started. Tutorial categories: The tutorials fall into a few broad categories. Some examples in each category are listed below. Making an LED blink (the \"Hello World\" equivalent in the electronics world) Blinky on Arduino Zero hardware Blinky on Olimex/STM32F407ZGT6 Cortex-M4 hardware Blinky on nRF52 Development Kit from Nordic Semiconductor Note: This supports BLE. Blinky on Redbear Nano2 Navigating the code and adding functionality Adding more repositories to your project Adding a unit test for a package Adding task to manage multiple events Bluetooth Low Energy Running the example BLE app included in the repo Working with another example BLE app for a peripheral device Using NewtMgr Enabling remote communication with a device running Mynewt OS Additional network connectivity Connect Arduino to a Wi-Fi network Send us an email on the dev@ mailing list if you have comments or suggestions! If you haven't joined the mailing list, you will find the links here .","title":"toc"},{"location":"os/tutorials/tutorials/#tutorials","text":"If the introduction to Mynewt has piqued your interest and you want to familiarize yourself with some of its functionality, this series of tutorials is for you. The lessons are aimed at the beginner. The full list of tutorials can be seen in the navigation bar on the left. New ones are being constantly added and will show up there automatically.","title":"Tutorials"},{"location":"os/tutorials/tutorials/#prerequisites","text":"You have installed Docker container of Newt tool and toolchains or you have installed them natively on your machine You have created a new project space (directory structure) and populated it with the core code repository (apache-mynewt-core) or know how to as explained in Creating Your First Project . You have at least one of the supported development boards: Arduino Zero hardware Olimex/STM32F407ZGT6 Cortex-M4 hardware nRF52 Development Kit from Nordic Semiconductor The Nordic nrf52 developer kit supports Bluetooth Low Energy. We are always looking to add new hardware to the list, so if you want to develop the required Board Support Package (bsp) and/or Hardware Abstraction Layer (HAL) for a new board, you can look here to get started.","title":"Prerequisites:"},{"location":"os/tutorials/tutorials/#tutorial-categories","text":"The tutorials fall into a few broad categories. Some examples in each category are listed below. Making an LED blink (the \"Hello World\" equivalent in the electronics world) Blinky on Arduino Zero hardware Blinky on Olimex/STM32F407ZGT6 Cortex-M4 hardware Blinky on nRF52 Development Kit from Nordic Semiconductor Note: This supports BLE. Blinky on Redbear Nano2 Navigating the code and adding functionality Adding more repositories to your project Adding a unit test for a package Adding task to manage multiple events Bluetooth Low Energy Running the example BLE app included in the repo Working with another example BLE app for a peripheral device Using NewtMgr Enabling remote communication with a device running Mynewt OS Additional network connectivity Connect Arduino to a Wi-Fi network Send us an email on the dev@ mailing list if you have comments or suggestions! If you haven't joined the mailing list, you will find the links here .","title":"Tutorial categories:"},{"location":"os/tutorials/unit_test/","text":"Write a Test Suite for a Package This document presents a tutorial which guides the reader through writing a test suite for a Mynewt package (new or existing). Introduction Writing a test suite involves using the libs/testutil package within Mynewt core os. The testutil library provides the interface to the newt command tool and also provides the compile time hooks to include test suites into your code. Review the [ testutil introduction page ] (../modules/testutil/testutil.md) to learn about how the library works. Identify Your Package Identify the package for which you are writing a test suite. For this example we will use libs/json . To create a new package, see this Tutorial . Modify Pkg.yml Edit the package ( pkg.yml ) file for your package and add the test dependency for the Mynewt core OS libs/testutil . pkg . deps . TEST: - libs/testutil Create Your Test Suite Template Create a subdirectory test under your package main directory. Create a file pair for your test code and header files within the test directory created above. Below shows the libs/json directory within the Mynewt core, including the test directory. In this example, we used the convention test_xxx.c/h (in this case test_json ). \u251c\u2500\u2500 MSJSON_COPYING \u251c\u2500\u2500 include \u2502 \u2514\u2500\u2500 json \u2502 \u2514\u2500\u2500 json . h \u251c\u2500\u2500 pkg . yml \u2514\u2500\u2500 src \u251c\u2500\u2500 json_decode . c \u251c\u2500\u2500 json_encode . c \u2514\u2500\u2500 test \u251c\u2500\u2500 test_json . c \u2514\u2500\u2500 test_json . h Create Your Test Suite Code Edit the test_json.c file and add your test suite definition. NOTE that the test suite code requires #include <testutil/testutil.h> to get the Mynewt testutil definitions. Your test suite test_json.c file contains at a minimum two functions: A test Suite which is empty for now, but will contain calls to your test cases. A main function which must be #ifdef 'd using MYNEWT_SELFTEST to ensure that is does not get compiled in when this test suite is run with test suites from other packages Below shows the contents of the test_json.c file. #include <testutil/testutil.h> TEST_SUITE ( test_json_suite ) { /* empty for now, add test cases later */ } #ifdef MYNEWT_SELFTEST int main ( int argc , char **argv ) { tu_config . tc_print_results = 1 ; tu_init (); test_json_suite (); return tu_any_failed ; } #endif Try It Out At this point, you have a working test suite with no tests. This will by default pass the test. Your output will look something like this. You can use the newt test command to run the unit tests for any package. Just include the package name. These unit tests run via the project unittest which is a native project automatically included in the core os package. Below shows some of the test output of this command. $ newt test libs/json Archiving util . a Linking test_json Testing package libs/json Test ... /bin/unittest/libs/json/test_json ok! Create a Test To create a test within your test suite, there are two things to do. Add the functions to your test suite Implement the function using the testutil macros For this tutorial we will create two functions: one to test a simple json encode and one to test the decode of this simple message to ensure its coherent. Follow These steps; 1. Create function prototypes in test_json.h for your test functions. A macro in testutil.h hides the actual prototype, but as of this writing the prototype is int test_func(void); . #ifndef TEST_JSON_H #define TEST_JSON_H TEST_CASE_DECL ( test_json_simple_encode ); TEST_CASE_DECL ( test_json_simple_decode ); #endif /* TEST_JSON_H 2. create a new file test_json_simple.c to define these two functions. For now you can stub these functions. Below shows the contents of this file. The functions are defined using macros which reference back to the testutil library so the test can be enumerated and recorded automatically. #include \"testutil/testutil.h\" #include \"test_json.h\" TEST_CASE ( test_json_simple_encode ) { } TEST_CASE ( test_json_simple_decode ) { } #endif /* TEST_JSON_H 3. Add the tests to your test suite in test_json.c as shown below. TEST_SUITE ( test_json_suite ) { test_json_simple_encode (); test_json_simple_decode (); } Your test suite should still pass as shown below $newt test libs/json Testing package libs/json Test ... /bin/unittest/libs/json/test_json ok! Add Contents to your Tests At this point, you can add contents to your test and verify that the test suites pass. For now, lets just add a simple failure to show what it would look like when running from Newt. Edit test_json_simple.c and add a TEST_ASSERT to a test function. The test assert will fail if its argument is false . TEST_CASE ( test_json_simple_encode ) { TEST_ASSERT ( 0 ); } When running newt, you will see the test suite fails with something like the message shown below. Testing package libs/json [ FAIL ] test_json_suite/ ( null ) |test_json_simple . c: 24 | failed assertion: 0 Error : Test crashed: .. /bin/unittest/libs/json/test_json exit status 1 Congratulations Now you can begin the work of adding your test cases and test. Testing on your target","title":"Write a Test Suite for a Package"},{"location":"os/tutorials/unit_test/#write-a-test-suite-for-a-package","text":"This document presents a tutorial which guides the reader through writing a test suite for a Mynewt package (new or existing).","title":"Write a Test Suite for a Package"},{"location":"os/tutorials/unit_test/#introduction","text":"Writing a test suite involves using the libs/testutil package within Mynewt core os. The testutil library provides the interface to the newt command tool and also provides the compile time hooks to include test suites into your code. Review the [ testutil introduction page ] (../modules/testutil/testutil.md) to learn about how the library works.","title":"Introduction"},{"location":"os/tutorials/unit_test/#identify-your-package","text":"Identify the package for which you are writing a test suite. For this example we will use libs/json . To create a new package, see this Tutorial .","title":"Identify Your Package"},{"location":"os/tutorials/unit_test/#modify-pkgyml","text":"Edit the package ( pkg.yml ) file for your package and add the test dependency for the Mynewt core OS libs/testutil . pkg . deps . TEST: - libs/testutil","title":"Modify Pkg.yml"},{"location":"os/tutorials/unit_test/#create-your-test-suite-template","text":"Create a subdirectory test under your package main directory. Create a file pair for your test code and header files within the test directory created above. Below shows the libs/json directory within the Mynewt core, including the test directory. In this example, we used the convention test_xxx.c/h (in this case test_json ). \u251c\u2500\u2500 MSJSON_COPYING \u251c\u2500\u2500 include \u2502 \u2514\u2500\u2500 json \u2502 \u2514\u2500\u2500 json . h \u251c\u2500\u2500 pkg . yml \u2514\u2500\u2500 src \u251c\u2500\u2500 json_decode . c \u251c\u2500\u2500 json_encode . c \u2514\u2500\u2500 test \u251c\u2500\u2500 test_json . c \u2514\u2500\u2500 test_json . h","title":"Create Your Test Suite Template"},{"location":"os/tutorials/unit_test/#create-your-test-suite-code","text":"Edit the test_json.c file and add your test suite definition. NOTE that the test suite code requires #include <testutil/testutil.h> to get the Mynewt testutil definitions. Your test suite test_json.c file contains at a minimum two functions: A test Suite which is empty for now, but will contain calls to your test cases. A main function which must be #ifdef 'd using MYNEWT_SELFTEST to ensure that is does not get compiled in when this test suite is run with test suites from other packages Below shows the contents of the test_json.c file. #include <testutil/testutil.h> TEST_SUITE ( test_json_suite ) { /* empty for now, add test cases later */ } #ifdef MYNEWT_SELFTEST int main ( int argc , char **argv ) { tu_config . tc_print_results = 1 ; tu_init (); test_json_suite (); return tu_any_failed ; } #endif","title":"Create Your Test Suite Code"},{"location":"os/tutorials/unit_test/#try-it-out","text":"At this point, you have a working test suite with no tests. This will by default pass the test. Your output will look something like this. You can use the newt test command to run the unit tests for any package. Just include the package name. These unit tests run via the project unittest which is a native project automatically included in the core os package. Below shows some of the test output of this command. $ newt test libs/json Archiving util . a Linking test_json Testing package libs/json Test ... /bin/unittest/libs/json/test_json ok!","title":"Try It Out"},{"location":"os/tutorials/unit_test/#create-a-test","text":"To create a test within your test suite, there are two things to do. Add the functions to your test suite Implement the function using the testutil macros For this tutorial we will create two functions: one to test a simple json encode and one to test the decode of this simple message to ensure its coherent. Follow These steps; 1. Create function prototypes in test_json.h for your test functions. A macro in testutil.h hides the actual prototype, but as of this writing the prototype is int test_func(void); . #ifndef TEST_JSON_H #define TEST_JSON_H TEST_CASE_DECL ( test_json_simple_encode ); TEST_CASE_DECL ( test_json_simple_decode ); #endif /* TEST_JSON_H 2. create a new file test_json_simple.c to define these two functions. For now you can stub these functions. Below shows the contents of this file. The functions are defined using macros which reference back to the testutil library so the test can be enumerated and recorded automatically. #include \"testutil/testutil.h\" #include \"test_json.h\" TEST_CASE ( test_json_simple_encode ) { } TEST_CASE ( test_json_simple_decode ) { } #endif /* TEST_JSON_H 3. Add the tests to your test suite in test_json.c as shown below. TEST_SUITE ( test_json_suite ) { test_json_simple_encode (); test_json_simple_decode (); } Your test suite should still pass as shown below $newt test libs/json Testing package libs/json Test ... /bin/unittest/libs/json/test_json ok!","title":"Create a Test"},{"location":"os/tutorials/unit_test/#add-contents-to-your-tests","text":"At this point, you can add contents to your test and verify that the test suites pass. For now, lets just add a simple failure to show what it would look like when running from Newt. Edit test_json_simple.c and add a TEST_ASSERT to a test function. The test assert will fail if its argument is false . TEST_CASE ( test_json_simple_encode ) { TEST_ASSERT ( 0 ); } When running newt, you will see the test suite fails with something like the message shown below. Testing package libs/json [ FAIL ] test_json_suite/ ( null ) |test_json_simple . c: 24 | failed assertion: 0 Error : Test crashed: .. /bin/unittest/libs/json/test_json exit status 1","title":"Add Contents to your Tests"},{"location":"os/tutorials/unit_test/#congratulations","text":"Now you can begin the work of adding your test cases and test.","title":"Congratulations"},{"location":"os/tutorials/unit_test/#testing-on-your-target","text":"","title":"Testing on your target"},{"location":"os/tutorials/wi-fi_on_arduino/","text":"Enable Wi-Fi on Arduino MKR1000 This tutorial shows you how to enable Wi-Fi on an Arduino MKR1000 board and connect to a Wi-Fi network. Prerequisites Ensure that you have met the following prerequisites before continuing with this tutorial: Have an Arduino MKR1000 board. Have Internet connectivity to fetch remote Mynewt components. Have a computer to build a Mynewt application and connect to the board over USB. Have a Micro-USB cable to connect the board and the computer. Have local Wi-Fi network that the computer is connected to and that the MKR1000 board can join. Have a Serial Port Setup . Have a Segger J-Link Debug Probe . Have a J-Link 9 pin Cortex-M Adapter that allows JTAG, SWD and SWO connections between J-Link and Cortex M based target hardware systems Install the Segger JLINK Software and documentation pack . Install the Newt tool and toolchains (See Basic Setup ). Create a project space (directory structure) and populated it with the core code repository (apache-mynewt-core) or know how to as explained in Creating Your First Project . Read the Mynewt OS Concepts section. Create a Project Create a new project if you do not have an existing one. You can skip this step and proceed to fetch external packages if you already created a project. Run the following commands to create a new project: $ mkdir ~/dev $ cd ~/dev $ newt new arduinowifi Downloading project skeleton from apache/incubator-mynewt-blinky... Installing skeleton in arduinowifi... Project arduinowifi successfully created. $ cd arduinowifi $ newt install apache-mynewt-core $ Fetch External Packages Mynewt uses source code provided directly from the chip manufacturer for low level operations. Sometimes this code is licensed only for the specific manufacturer of the chipset and cannot live in the Apache Mynewt repository. That happens to be the case for the Arduino Zero board which uses Atmel SAMD21. Runtime's git hub repository hosts such external third-party packages and the Newt tool can fetch them. To fetch the package with MCU support for Atmel SAMD21 for Arduino Zero from the Runtime git repository, you need to add the repository to the project.yml file in your base project directory. Mynewt uses source code provided directly from the chip manufacturer for low level operations. Sometimes this code is licensed only for the specific manufacturer of the chipset and cannot live in the Apache Mynewt repository. That happens to be the case for the Arduino Zero board which uses Atmel SAMD21. Runtime's github repository hosts such external third-party packages and the Newt tool can fetch them. To fetch the package with MCU support for Atmel SAMD21 for Arduino Zero from the Runtime git repository, you need to add the repository to the project.yml file in your base project directory ( arduinowifi ). Here is an example project.yml file with the Arduino Zero repository added. The sections with mynewt_arduino_zero that need to be added to your project file are highlighted. Note: On Windows platforms: You need to set vers to 0-dev and use the latest master branch for both repositories. $ more project.yml project.name: \"my_project\" project.repositories: - apache-mynewt-core - mynewt_arduino_zero repository.apache-mynewt-core: type: github vers: 1-latest user: apache repo: incubator-mynewt-core repository.mynewt_arduino_zero: type: github vers: 1-latest user: runtimeco repo: mynewt_arduino_zero $ Install the project dependencies using the newt install command (you can specify -v for verbose output): $ newt install apache-mynewt-core mynewt_arduino_zero $ NOTE: If there has been a new release of a repo used in your project since you last installed it, the 1-latest version for the repo in the project.yml file will refer to the new release and will not match the installed files. In that case you will get an error message saying so and you will need to run newt upgrade to overwrite the existing files with the latest codebase. Create a Target for the Bootloader You need to create two targets for the MKR1000 board, one for the bootloader and one for the winc1500_wifi application. Run the following newt target commands, from your project directory, to create a bootloader target. We name the target mkr1000_boot . $ newt target create mkr1000_boot $ newt target set mkr1000_boot bsp=@mynewt_arduino_zero/hw/bsp/arduino_mkr1000 $ newt target set mkr1000_boot app=@apache-mynewt-core/apps/boot $ newt target set mkr1000_boot build_profile=optimized $ newt target set mkr1000_boot syscfg=BSP_ARDUINO_ZERO_PRO=1 Create a Target for the Wi-Fi Application Run the following newt target commands to create a target for the winc1500_wifi application in the arduino repository. We name the application target mkr1000_wifi . $ newt target create mkr1000_wifi $ newt target set mkr1000_wifi app=@mynewt_arduino_zero/apps/winc1500_wifi $ newt target set mkr1000_wifi bsp=@mynewt_arduino_zero/hw/bsp/arduino_mkr1000 $ newt target set mkr1000_wifi build_profile=debug $ newt target set mkr1000_boot syscfg=BSP_ARDUINO_ZERO_PRO=1 Build the Bootloader Run the newt build mkr1000_boot command to build the bootloader: $ newt build mkr1000_boot Building target targets/mkr1000_boot Compiling repos/apache-mynewt-core/boot/bootutil/src/image_rsa.c Compiling repos/apache-mynewt-core/boot/bootutil/src/image_ec256.c Compiling repos/apache-mynewt-core/crypto/mbedtls/src/aes.c Compiling repos/apache-mynewt-core/boot/bootutil/src/image_ec.c Compiling repos/apache-mynewt-core/boot/bootutil/src/image_validate.c Compiling repos/apache-mynewt-core/apps/boot/src/boot.c ... Archiving util_mem.a Linking ~/dev/arduinowifi/bin/targets/mkr1000_boot/app/apps/boot/boot.elf Target successfully built: targets/mkr1000_boot $ Build the Wi-Fi Application Run the newt build mkr1000_wifi command to build the wi-fi application image: $newt build mkr1000_wifi Building target targets/mkr1000_wifi Compiling repos/apache-mynewt-core/boot/bootutil/src/image_ec.c Compiling repos/apache-mynewt-core/boot/bootutil/src/image_ec256.c Compiling repos/apache-mynewt-core/boot/bootutil/src/image_rsa.c Compiling repos/apache-mynewt-core/boot/bootutil/src/image_validate.c Compiling repos/apache-mynewt-core/boot/bootutil/src/loader.c ... Archiving util_mem.a Linking ~/dev/arduinowifi/bin/targets/mkr1000_wifi/app/apps/winc1500_wifi/winc1500_wifi.elf Target successfully built: targets/mkr1000_wifi $ Sign and Create the Wi-Fi Application Image Run the newt create-image mkr1000_wifi 1.0.0 command to sign and create an image file for the Wi-Fi application. You may assign an arbitrary version (e.g. 1.0.0) number. $newt create-image mkr1000_wifi 1.0.0 Compiling bin/targets/mkr1000_wifi/generated/src/mkr1000_wifi-sysinit-app.c Archiving mkr1000_wifi-sysinit-app.a Linking ~/dev/arduinowifi/bin/targets/mkr1000_wifi/app/apps/winc1500_wifi/winc1500_wifi.elf App image succesfully generated: ~/dev/arduinowifi/bin/targets/mkr1000_wifi/app/apps/winc1500_wifi/winc1500_wifi.img $ Connect to the Board Connect your computer to the MKR1000 board with the Micro-USB cable. Connect the debug probe to the JTAG port on the board using the Jlink 9-pin adapter and cable. Mynewt will download and debug the target through this port. You should see a green LED come on and indicates the board has power. ### Load the Bootloader onto the Board Run the `newt load mkr1000_boot` command to load the bootloader onto the board: $ newt load mkr1000_boot Loading bootloader $ ### Load the Wi-Fi Application Image onto the Board Run the `newt load mkr1000_wifi` command to load the wifi application onto the board: $ newt load mkr1000_wifi Loading app image into slot 1 $ ### Setup a Serial Connection Between Your Computer and the Board Set up a serial connection from your computer to the MKR1000 board (See [Serial Port Setup](/os/get_started/serial_access.md)). On the MKR1000 board, the TX pin is PIN 14 and the RX pin in PIN 13. ![Serial Connection to MKR1000](pics/mkr1000-serial.jpg \"Connecting to the MKR1000 Serial Port\") Locate the port, in the /dev directory on your computer, that the serial connection uses. The format of the port name is platform dependent: * Mac OS uses the format `tty.usbserial- `. * Linux uses the format `TTYUSB `, where `N` is a number. For example, TTYUSB2. * MinGW on Windows uses the format `ttyS `, where `N` is a number. You must map the port name to a Windows COM port: ` /dev/ttyS ` maps to `COM `. For example, `/dev/ttyS2` maps to `COM3`. You can also use the Windows Device Manager to find the COM port number. $ ls /dev/tty*usbserial* /dev/tty.usbserial-1d13 $ ### Start Wi-Fi via console Use a terminal emulation program to communicate with the board over the serial port. This tutorial shows a Minicom set up. Run the minicom command with the serial port you located on your computer: **Note:** On Windows, you can use the PuTTY application. $ minicom -D /dev/tty.usbserial-1d13 -b 115200 Type `wifi start` to start Wi-Fi. Welcome to minicom 2.7 OPTIONS: Compiled on Mar 18 2016, 04:59:47. Port /dev/tty.usbserial-1d13, 17:06:09 Press Meta-Z for help on special keys wifi start 3293703:(APP)(INFO)Chip ID 1503a0 (APP)(INFO)Firmware ver : 19.4.4 (APP)(INFO)Min driver ver : 19.3.0 (APP)(INFO)Curr driver ver: 19.3.0 wifi_init : 0 Connect to the local Wi-Fi network. Note that the MKR1000 board only supports 2.4 GHz Wi-Fi networks. Run the `wifi connect` command and specify your network and . After you are connected to your wi-fi network, run the `net service` command to start network services. wifi connect <ssid> <password> 3362937:wifi_request_scan : 0 3363843:scan_results 9: 0 3363855:wifi_connect : 0 3364852:connect_done : 0 3364861:dhcp done 10.0.0.4 3365470:get sys time response 2017.3.31-0.9.57 net service The board is connected to the network succesfully and has IP address: 10.0.0.4 ### Establish TCP Connection and Talk! From a terminal on your computer, telnet to ports 7, 9, or 19 using the IP address your board has been assigned. Type something on this terminal and see the console output (on minicom). Can you see the difference in the behaviors? $telnet 10.0.0.4 7 Trying 10.0.0.4... Connected to 10.0.0.4. Escape character is '^]'. hello hello ^] telnet> q $ One port echoes whatever is typed, one discards everything it gets, and the third spews out bits constantly. Type `wifi stop` to disable WiFi on the Arduino board.","title":"Enable Wi-Fi on Arduino MKR1000"},{"location":"os/tutorials/wi-fi_on_arduino/#enable-wi-fi-on-arduino-mkr1000","text":"This tutorial shows you how to enable Wi-Fi on an Arduino MKR1000 board and connect to a Wi-Fi network.","title":"Enable Wi-Fi on Arduino MKR1000"},{"location":"os/tutorials/wi-fi_on_arduino/#prerequisites","text":"Ensure that you have met the following prerequisites before continuing with this tutorial: Have an Arduino MKR1000 board. Have Internet connectivity to fetch remote Mynewt components. Have a computer to build a Mynewt application and connect to the board over USB. Have a Micro-USB cable to connect the board and the computer. Have local Wi-Fi network that the computer is connected to and that the MKR1000 board can join. Have a Serial Port Setup . Have a Segger J-Link Debug Probe . Have a J-Link 9 pin Cortex-M Adapter that allows JTAG, SWD and SWO connections between J-Link and Cortex M based target hardware systems Install the Segger JLINK Software and documentation pack . Install the Newt tool and toolchains (See Basic Setup ). Create a project space (directory structure) and populated it with the core code repository (apache-mynewt-core) or know how to as explained in Creating Your First Project . Read the Mynewt OS Concepts section.","title":"Prerequisites"},{"location":"os/tutorials/wi-fi_on_arduino/#create-a-project","text":"Create a new project if you do not have an existing one. You can skip this step and proceed to fetch external packages if you already created a project. Run the following commands to create a new project: $ mkdir ~/dev $ cd ~/dev $ newt new arduinowifi Downloading project skeleton from apache/incubator-mynewt-blinky... Installing skeleton in arduinowifi... Project arduinowifi successfully created. $ cd arduinowifi $ newt install apache-mynewt-core $","title":"Create a Project"},{"location":"os/tutorials/wi-fi_on_arduino/#fetch-external-packages","text":"Mynewt uses source code provided directly from the chip manufacturer for low level operations. Sometimes this code is licensed only for the specific manufacturer of the chipset and cannot live in the Apache Mynewt repository. That happens to be the case for the Arduino Zero board which uses Atmel SAMD21. Runtime's git hub repository hosts such external third-party packages and the Newt tool can fetch them. To fetch the package with MCU support for Atmel SAMD21 for Arduino Zero from the Runtime git repository, you need to add the repository to the project.yml file in your base project directory. Mynewt uses source code provided directly from the chip manufacturer for low level operations. Sometimes this code is licensed only for the specific manufacturer of the chipset and cannot live in the Apache Mynewt repository. That happens to be the case for the Arduino Zero board which uses Atmel SAMD21. Runtime's github repository hosts such external third-party packages and the Newt tool can fetch them. To fetch the package with MCU support for Atmel SAMD21 for Arduino Zero from the Runtime git repository, you need to add the repository to the project.yml file in your base project directory ( arduinowifi ). Here is an example project.yml file with the Arduino Zero repository added. The sections with mynewt_arduino_zero that need to be added to your project file are highlighted. Note: On Windows platforms: You need to set vers to 0-dev and use the latest master branch for both repositories. $ more project.yml project.name: \"my_project\" project.repositories: - apache-mynewt-core - mynewt_arduino_zero repository.apache-mynewt-core: type: github vers: 1-latest user: apache repo: incubator-mynewt-core repository.mynewt_arduino_zero: type: github vers: 1-latest user: runtimeco repo: mynewt_arduino_zero $ Install the project dependencies using the newt install command (you can specify -v for verbose output): $ newt install apache-mynewt-core mynewt_arduino_zero $ NOTE: If there has been a new release of a repo used in your project since you last installed it, the 1-latest version for the repo in the project.yml file will refer to the new release and will not match the installed files. In that case you will get an error message saying so and you will need to run newt upgrade to overwrite the existing files with the latest codebase.","title":" Fetch External Packages"},{"location":"os/tutorials/wi-fi_on_arduino/#create-a-target-for-the-bootloader","text":"You need to create two targets for the MKR1000 board, one for the bootloader and one for the winc1500_wifi application. Run the following newt target commands, from your project directory, to create a bootloader target. We name the target mkr1000_boot . $ newt target create mkr1000_boot $ newt target set mkr1000_boot bsp=@mynewt_arduino_zero/hw/bsp/arduino_mkr1000 $ newt target set mkr1000_boot app=@apache-mynewt-core/apps/boot $ newt target set mkr1000_boot build_profile=optimized $ newt target set mkr1000_boot syscfg=BSP_ARDUINO_ZERO_PRO=1","title":"Create a Target for the Bootloader"},{"location":"os/tutorials/wi-fi_on_arduino/#create-a-target-for-the-wi-fi-application","text":"Run the following newt target commands to create a target for the winc1500_wifi application in the arduino repository. We name the application target mkr1000_wifi . $ newt target create mkr1000_wifi $ newt target set mkr1000_wifi app=@mynewt_arduino_zero/apps/winc1500_wifi $ newt target set mkr1000_wifi bsp=@mynewt_arduino_zero/hw/bsp/arduino_mkr1000 $ newt target set mkr1000_wifi build_profile=debug $ newt target set mkr1000_boot syscfg=BSP_ARDUINO_ZERO_PRO=1","title":"Create a Target for the Wi-Fi Application"},{"location":"os/tutorials/wi-fi_on_arduino/#build-the-bootloader","text":"Run the newt build mkr1000_boot command to build the bootloader: $ newt build mkr1000_boot Building target targets/mkr1000_boot Compiling repos/apache-mynewt-core/boot/bootutil/src/image_rsa.c Compiling repos/apache-mynewt-core/boot/bootutil/src/image_ec256.c Compiling repos/apache-mynewt-core/crypto/mbedtls/src/aes.c Compiling repos/apache-mynewt-core/boot/bootutil/src/image_ec.c Compiling repos/apache-mynewt-core/boot/bootutil/src/image_validate.c Compiling repos/apache-mynewt-core/apps/boot/src/boot.c ... Archiving util_mem.a Linking ~/dev/arduinowifi/bin/targets/mkr1000_boot/app/apps/boot/boot.elf Target successfully built: targets/mkr1000_boot $","title":"Build the Bootloader"},{"location":"os/tutorials/wi-fi_on_arduino/#build-the-wi-fi-application","text":"Run the newt build mkr1000_wifi command to build the wi-fi application image: $newt build mkr1000_wifi Building target targets/mkr1000_wifi Compiling repos/apache-mynewt-core/boot/bootutil/src/image_ec.c Compiling repos/apache-mynewt-core/boot/bootutil/src/image_ec256.c Compiling repos/apache-mynewt-core/boot/bootutil/src/image_rsa.c Compiling repos/apache-mynewt-core/boot/bootutil/src/image_validate.c Compiling repos/apache-mynewt-core/boot/bootutil/src/loader.c ... Archiving util_mem.a Linking ~/dev/arduinowifi/bin/targets/mkr1000_wifi/app/apps/winc1500_wifi/winc1500_wifi.elf Target successfully built: targets/mkr1000_wifi $","title":"Build the Wi-Fi Application"},{"location":"os/tutorials/wi-fi_on_arduino/#sign-and-create-the-wi-fi-application-image","text":"Run the newt create-image mkr1000_wifi 1.0.0 command to sign and create an image file for the Wi-Fi application. You may assign an arbitrary version (e.g. 1.0.0) number. $newt create-image mkr1000_wifi 1.0.0 Compiling bin/targets/mkr1000_wifi/generated/src/mkr1000_wifi-sysinit-app.c Archiving mkr1000_wifi-sysinit-app.a Linking ~/dev/arduinowifi/bin/targets/mkr1000_wifi/app/apps/winc1500_wifi/winc1500_wifi.elf App image succesfully generated: ~/dev/arduinowifi/bin/targets/mkr1000_wifi/app/apps/winc1500_wifi/winc1500_wifi.img $","title":"Sign and Create the Wi-Fi Application Image"},{"location":"os/tutorials/wi-fi_on_arduino/#connect-to-the-board","text":"Connect your computer to the MKR1000 board with the Micro-USB cable. Connect the debug probe to the JTAG port on the board using the Jlink 9-pin adapter and cable. Mynewt will download and debug the target through this port. You should see a green LED come on and indicates the board has power. ### Load the Bootloader onto the Board Run the `newt load mkr1000_boot` command to load the bootloader onto the board: $ newt load mkr1000_boot Loading bootloader $ ### Load the Wi-Fi Application Image onto the Board Run the `newt load mkr1000_wifi` command to load the wifi application onto the board: $ newt load mkr1000_wifi Loading app image into slot 1 $ ### Setup a Serial Connection Between Your Computer and the Board Set up a serial connection from your computer to the MKR1000 board (See [Serial Port Setup](/os/get_started/serial_access.md)). On the MKR1000 board, the TX pin is PIN 14 and the RX pin in PIN 13. ![Serial Connection to MKR1000](pics/mkr1000-serial.jpg \"Connecting to the MKR1000 Serial Port\") Locate the port, in the /dev directory on your computer, that the serial connection uses. The format of the port name is platform dependent: * Mac OS uses the format `tty.usbserial- `. * Linux uses the format `TTYUSB `, where `N` is a number. For example, TTYUSB2. * MinGW on Windows uses the format `ttyS `, where `N` is a number. You must map the port name to a Windows COM port: ` /dev/ttyS ` maps to `COM `. For example, `/dev/ttyS2` maps to `COM3`. You can also use the Windows Device Manager to find the COM port number. $ ls /dev/tty*usbserial* /dev/tty.usbserial-1d13 $ ### Start Wi-Fi via console Use a terminal emulation program to communicate with the board over the serial port. This tutorial shows a Minicom set up. Run the minicom command with the serial port you located on your computer: **Note:** On Windows, you can use the PuTTY application. $ minicom -D /dev/tty.usbserial-1d13 -b 115200 Type `wifi start` to start Wi-Fi. Welcome to minicom 2.7 OPTIONS: Compiled on Mar 18 2016, 04:59:47. Port /dev/tty.usbserial-1d13, 17:06:09 Press Meta-Z for help on special keys wifi start 3293703:(APP)(INFO)Chip ID 1503a0 (APP)(INFO)Firmware ver : 19.4.4 (APP)(INFO)Min driver ver : 19.3.0 (APP)(INFO)Curr driver ver: 19.3.0 wifi_init : 0 Connect to the local Wi-Fi network. Note that the MKR1000 board only supports 2.4 GHz Wi-Fi networks. Run the `wifi connect` command and specify your network and . After you are connected to your wi-fi network, run the `net service` command to start network services. wifi connect <ssid> <password> 3362937:wifi_request_scan : 0 3363843:scan_results 9: 0 3363855:wifi_connect : 0 3364852:connect_done : 0 3364861:dhcp done 10.0.0.4 3365470:get sys time response 2017.3.31-0.9.57 net service The board is connected to the network succesfully and has IP address: 10.0.0.4 ### Establish TCP Connection and Talk! From a terminal on your computer, telnet to ports 7, 9, or 19 using the IP address your board has been assigned. Type something on this terminal and see the console output (on minicom). Can you see the difference in the behaviors? $telnet 10.0.0.4 7 Trying 10.0.0.4... Connected to 10.0.0.4. Escape character is '^]'. hello hello ^] telnet> q $ One port echoes whatever is typed, one discards everything it gets, and the third spews out bits constantly. Type `wifi stop` to disable WiFi on the Arduino board.","title":"Connect to the Board"},{"location":"os/tutorials/bleprph/bleprph-adv/","text":"BLE Peripheral Project Advertising Overview A peripheral announces its presence to the world by broadcasting advertisements. An advertisement typically contains additional information about the peripheral sending it, such as the device name and an abbreviated list of supported services. The presence of this information helps a listening central to determine whether it is interested in connecting to the peripheral. Advertisements are quite limited in the amount of information they can contain, so only the most important information should be included. When a listening device receives an advertisement, it can choose to connect to the peripheral, or query the sender for more information. This second action is known as an active scan . A peripheral responds to an active scan with some extra information that it couldn't fit in its advertisement. This additional information is known as scan response data . bleprph does not configure any scan response data, so this feature is not discussed in the remainder of this tutorial. bleprph constantly broadcasts advertisements until a central connects to it. When a connection is terminated, bleprph resumes advertising. Let's take a look at bleprph 's advertisement code ( main.c ): /** * Enables advertising with the following parameters: * o General discoverable mode. * o Undirected connectable mode. */ static void bleprph_advertise ( void ) { struct ble_gap_adv_params adv_params ; struct ble_hs_adv_fields fields ; const char *name ; int rc ; /** * Set the advertisement data included in our advertisements: * o Flags (indicates advertisement type and other general info). * o Advertising tx power. * o Device name. * o 16-bit service UUIDs (alert notifications). */ memset ( &fields , 0 , sizeof fields ); /* Indicate that the flags field should be included; specify a value of 0 * to instruct the stack to fill the value in for us. */ fields . flags_is_present = 1 ; fields . flags = 0 ; /* Indicate that the TX power level field should be included; have the * stack fill this one automatically as well. This is done by assiging the * special value BLE_HS_ADV_TX_PWR_LVL_AUTO. */ fields . tx_pwr_lvl_is_present = 1 ; fields . tx_pwr_lvl = BLE_HS_ADV_TX_PWR_LVL_AUTO ; name = ble_svc_gap_device_name (); fields . name = ( uint8_t * ) name ; fields . name_len = strlen ( name ); fields . name_is_complete = 1 ; fields . uuids16 = ( uint16_t []){ GATT_SVR_SVC_ALERT_UUID }; fields . num_uuids16 = 1 ; fields . uuids16_is_complete = 1 ; rc = ble_gap_adv_set_fields ( &fields ); if ( rc != 0 ) { BLEPRPH_LOG ( ERROR , \"error setting advertisement data; rc=%d\\n\" , rc ); return ; } /* Begin advertising. */ memset ( &adv_params , 0 , sizeof adv_params ); adv_params . conn_mode = BLE_GAP_CONN_MODE_UND ; adv_params . disc_mode = BLE_GAP_DISC_MODE_GEN ; rc = ble_gap_adv_start ( BLE_ADDR_TYPE_PUBLIC , 0 , NULL , BLE_HS_FOREVER , &adv_params , bleprph_gap_event , NULL ); if ( rc != 0 ) { BLEPRPH_LOG ( ERROR , \"error enabling advertisement; rc=%d\\n\" , rc ); return ; } } Now let's examine this code in detail. Setting advertisement data A NimBLE peripheral specifies what information to include in its advertisements with the ble_gap_adv_set_fields() function. The fields argument specifies the fields and their contents to include in subsequent advertisements. The Bluetooth Core Specification Supplement defines a set of standard fields that can be included in an advertisement; the member variables of the struct ble_hs_adv_fields type correspond to these standard fields. Information that doesn't fit neatly into a standard field should be put in the manufacturing specific data field. As you can see in the above code listing, the struct ble_hs_adv_fields instance is allocated on the stack. It is OK to use the stack for this struct and the data it references, as the ble_gap_adv_set_fields() function makes a copy of all the advertisement data before it returns. bleprph doesn't take full advantange of this; it stores its device name in a static array. The code sets several members of the struct ble_hs_adv_fields instance. Most of them are quite straight-forward. However, the name_is_complete field requires some explanation. Bluetooth specifies two name-related advertisement fields: Shortened Local Name and Complete Local Name . Setting the name_is_complete variable to 1 or 0 tells NimBLE which of these two fields to include in advertisements. Some other advertisement fields also correspond to multiple variables in the field struct, so it is a good idea to review the ble_hs_adv_fields reference to make sure you get the details right in your app. Begin advertising An app starts advertising with ble_gap_adv_start() function. This function allows a lot of flexibility, and it might seem daunting at first glance. bleprph specifies a simple set of arguments that is appropriate for most peripherals. When getting started on a typical peripheral, we recommend you use the same arguments as bleprph , with the exception of the last two ( cb and cb_arg ; bleprph_gap_event and NULL in this case). These last two arguments will be specific to your app, so let's talk about them. cb is a callback function. It gets executed when a central connects to your peripheral after receiving an advertisement. The cb_arg argument gets passed to the cb callback. If your callback doesn't need the cb_arg parameter, you can do what bleprph does and pass NULL . Once a connection is established, the cb callback becomes permanently associated with the connection. All subsequent events related to the connection are communicated to your app via calls to this callback function. GAP event callbacks are an important part of building a BLE app, and we examine bleprph 's connection callback in detail in the next section of this tutorial. One final note: Your peripheral automatically stops advertising when a central connects to it. You can immediately resume advertising if you want to allow another central to connect, but you will need to do so explicitly by calling ble_gap_adv_start() again. Also, be aware NimBLE's default configuration only allows a single connection at a time. NimBLE supports multiple concurrent connections, but you must configure it to do so first.","title":"Advertising"},{"location":"os/tutorials/bleprph/bleprph-adv/#ble-peripheral-project","text":"","title":"BLE Peripheral Project"},{"location":"os/tutorials/bleprph/bleprph-adv/#advertising","text":"","title":"Advertising"},{"location":"os/tutorials/bleprph/bleprph-adv/#overview","text":"A peripheral announces its presence to the world by broadcasting advertisements. An advertisement typically contains additional information about the peripheral sending it, such as the device name and an abbreviated list of supported services. The presence of this information helps a listening central to determine whether it is interested in connecting to the peripheral. Advertisements are quite limited in the amount of information they can contain, so only the most important information should be included. When a listening device receives an advertisement, it can choose to connect to the peripheral, or query the sender for more information. This second action is known as an active scan . A peripheral responds to an active scan with some extra information that it couldn't fit in its advertisement. This additional information is known as scan response data . bleprph does not configure any scan response data, so this feature is not discussed in the remainder of this tutorial. bleprph constantly broadcasts advertisements until a central connects to it. When a connection is terminated, bleprph resumes advertising. Let's take a look at bleprph 's advertisement code ( main.c ): /** * Enables advertising with the following parameters: * o General discoverable mode. * o Undirected connectable mode. */ static void bleprph_advertise ( void ) { struct ble_gap_adv_params adv_params ; struct ble_hs_adv_fields fields ; const char *name ; int rc ; /** * Set the advertisement data included in our advertisements: * o Flags (indicates advertisement type and other general info). * o Advertising tx power. * o Device name. * o 16-bit service UUIDs (alert notifications). */ memset ( &fields , 0 , sizeof fields ); /* Indicate that the flags field should be included; specify a value of 0 * to instruct the stack to fill the value in for us. */ fields . flags_is_present = 1 ; fields . flags = 0 ; /* Indicate that the TX power level field should be included; have the * stack fill this one automatically as well. This is done by assiging the * special value BLE_HS_ADV_TX_PWR_LVL_AUTO. */ fields . tx_pwr_lvl_is_present = 1 ; fields . tx_pwr_lvl = BLE_HS_ADV_TX_PWR_LVL_AUTO ; name = ble_svc_gap_device_name (); fields . name = ( uint8_t * ) name ; fields . name_len = strlen ( name ); fields . name_is_complete = 1 ; fields . uuids16 = ( uint16_t []){ GATT_SVR_SVC_ALERT_UUID }; fields . num_uuids16 = 1 ; fields . uuids16_is_complete = 1 ; rc = ble_gap_adv_set_fields ( &fields ); if ( rc != 0 ) { BLEPRPH_LOG ( ERROR , \"error setting advertisement data; rc=%d\\n\" , rc ); return ; } /* Begin advertising. */ memset ( &adv_params , 0 , sizeof adv_params ); adv_params . conn_mode = BLE_GAP_CONN_MODE_UND ; adv_params . disc_mode = BLE_GAP_DISC_MODE_GEN ; rc = ble_gap_adv_start ( BLE_ADDR_TYPE_PUBLIC , 0 , NULL , BLE_HS_FOREVER , &adv_params , bleprph_gap_event , NULL ); if ( rc != 0 ) { BLEPRPH_LOG ( ERROR , \"error enabling advertisement; rc=%d\\n\" , rc ); return ; } } Now let's examine this code in detail.","title":"Overview"},{"location":"os/tutorials/bleprph/bleprph-adv/#setting-advertisement-data","text":"A NimBLE peripheral specifies what information to include in its advertisements with the ble_gap_adv_set_fields() function. The fields argument specifies the fields and their contents to include in subsequent advertisements. The Bluetooth Core Specification Supplement defines a set of standard fields that can be included in an advertisement; the member variables of the struct ble_hs_adv_fields type correspond to these standard fields. Information that doesn't fit neatly into a standard field should be put in the manufacturing specific data field. As you can see in the above code listing, the struct ble_hs_adv_fields instance is allocated on the stack. It is OK to use the stack for this struct and the data it references, as the ble_gap_adv_set_fields() function makes a copy of all the advertisement data before it returns. bleprph doesn't take full advantange of this; it stores its device name in a static array. The code sets several members of the struct ble_hs_adv_fields instance. Most of them are quite straight-forward. However, the name_is_complete field requires some explanation. Bluetooth specifies two name-related advertisement fields: Shortened Local Name and Complete Local Name . Setting the name_is_complete variable to 1 or 0 tells NimBLE which of these two fields to include in advertisements. Some other advertisement fields also correspond to multiple variables in the field struct, so it is a good idea to review the ble_hs_adv_fields reference to make sure you get the details right in your app.","title":"Setting advertisement data"},{"location":"os/tutorials/bleprph/bleprph-adv/#begin-advertising","text":"An app starts advertising with ble_gap_adv_start() function. This function allows a lot of flexibility, and it might seem daunting at first glance. bleprph specifies a simple set of arguments that is appropriate for most peripherals. When getting started on a typical peripheral, we recommend you use the same arguments as bleprph , with the exception of the last two ( cb and cb_arg ; bleprph_gap_event and NULL in this case). These last two arguments will be specific to your app, so let's talk about them. cb is a callback function. It gets executed when a central connects to your peripheral after receiving an advertisement. The cb_arg argument gets passed to the cb callback. If your callback doesn't need the cb_arg parameter, you can do what bleprph does and pass NULL . Once a connection is established, the cb callback becomes permanently associated with the connection. All subsequent events related to the connection are communicated to your app via calls to this callback function. GAP event callbacks are an important part of building a BLE app, and we examine bleprph 's connection callback in detail in the next section of this tutorial. One final note: Your peripheral automatically stops advertising when a central connects to it. You can immediately resume advertising if you want to allow another central to connect, but you will need to do so explicitly by calling ble_gap_adv_start() again. Also, be aware NimBLE's default configuration only allows a single connection at a time. NimBLE supports multiple concurrent connections, but you must configure it to do so first.","title":"Begin advertising"},{"location":"os/tutorials/bleprph/bleprph-app/","text":"BLE Peripheral Project Overview Now that we've gone through how BLE Apps are contructed, how they function, and how all the parts fit together let's try out a BLE Peripheral App to see how it all works. Prerequisites You should already have completed the previous BLE Tiny Project , though it's not required. You should have a BLE Central App of some sort to connect with. On Mac OS or iOS, you can use LightBlue which is a free app to browse and connect to BLE Peripheral devices. Create a New Target You can create a new project instead, but this tutorial will simply use the previously created bletiny project and add a new target for the BLE Peripheral $ newt target create myperiph Target targets/myperiph successfully created $ newt target set myperiph bsp=@apache-mynewt-core/hw/bsp/nrf52dk Target targets/myperiph successfully set target.bsp to @apache-mynewt-core/hw/bsp/nrf52dk $ newt target set myperiph app=@apache-mynewt-core/apps/bleprph Target targets/myperiph successfully set target.app to @apache-mynewt-core/apps/bleprph $ newt target set myperiph build_profile=optimized Target targets/myperiph successfully set target.build_profile to optimized $ newt build myblerph Building target targets/myperiph ... Linking ~/dev/nrf52dk/bin/targets/myperiph/app/apps/bleprph/bleprph.elf Target successfully built: targets/myperiph $ newt create-image myperiph 1.0.0 App image succesfully generated: ~/dev/nrf52dk/bin/targets/myperiph/app/apps/bleprph/bleprph.img $ newt load myperiph Loading app image into slot 1 Now if you reset the board, and fire up your BLE Central App, you should see a new peripheral device called 'nimble-bleprph'. Now that you can see the device, you can begin to interact with the advertised service. Click on the device and you'll establish a connection. Now that you're connected, you can see the Services that are being advertised. Scroll to the bottom and you will see a Read Characteristic, and a Read/Write Characteristic. Just click on the Read Write Characteristic and you will see the existing value. Type in a new value. And you will see the new value reflected. If you still have your console connected, you will be able to see the connection requests, and pairing, happen on the device as well. 258894:[ts=2022609336ssb, mod=64 level=1] connection established; status=0 handle=1 our_ota_addr_type=0 our_ota_addr=0a:0a:0a:0a:0a:0a our_id_addr_type=0 our_id_addr=0a:0a:0a:0a:0a:0a peer_ota_addr_type=1 peer_ota_addr=7f:be:d4:44:c0:d4 peer_id_addr_type=1 peer_id_addr=7f:be:d4:44:c0:d4 conn_itvl=24 conn_latency=0 supervision_timeout=72 encrypted=0 authenticated=0 bonded=0 258904:[ts=2022687456ssb, mod=64 level=1] 258917:[ts=2022789012ssb, mod=64 level=1] mtu update event; conn_handle=1 cid=4 mtu=185 258925:[ts=2022851508ssb, mod=64 level=1] subscribe event; conn_handle=1 attr_handle=14 reason=1 prevn=0 curn=0 previ=0 curi=1 261486:[ts=2042859320ssb, mod=64 level=1] encryption change event; status=0 handle=1 our_ota_addr_type=0 our_ota_addr=0a:0a:0a:0a:0a:0a our_id_addr_type=0 our_id_addr=0a:0a:0a:0a:0a:0a peer_ota_addr_type=1 peer_ota_addr=7f:be:d4:44:c0:d4 peer_id_addr_type=1 peer_id_addr=7f:be:d4:44:c0:d4 conn_itvl=24 conn_latency=0 supervision_timeout=72 encrypted=1 authenticated=0 bonded=1 261496:[ts=2042937440ssb, mod=64 level=1] Congratulations! You've just built and connected your first BLE Peripheral device!","title":"BLE Peripheral App"},{"location":"os/tutorials/bleprph/bleprph-app/#ble-peripheral-project","text":"","title":"BLE Peripheral Project"},{"location":"os/tutorials/bleprph/bleprph-app/#overview","text":"Now that we've gone through how BLE Apps are contructed, how they function, and how all the parts fit together let's try out a BLE Peripheral App to see how it all works.","title":"Overview"},{"location":"os/tutorials/bleprph/bleprph-app/#prerequisites","text":"You should already have completed the previous BLE Tiny Project , though it's not required. You should have a BLE Central App of some sort to connect with. On Mac OS or iOS, you can use LightBlue which is a free app to browse and connect to BLE Peripheral devices.","title":"Prerequisites"},{"location":"os/tutorials/bleprph/bleprph-app/#create-a-new-target","text":"You can create a new project instead, but this tutorial will simply use the previously created bletiny project and add a new target for the BLE Peripheral $ newt target create myperiph Target targets/myperiph successfully created $ newt target set myperiph bsp=@apache-mynewt-core/hw/bsp/nrf52dk Target targets/myperiph successfully set target.bsp to @apache-mynewt-core/hw/bsp/nrf52dk $ newt target set myperiph app=@apache-mynewt-core/apps/bleprph Target targets/myperiph successfully set target.app to @apache-mynewt-core/apps/bleprph $ newt target set myperiph build_profile=optimized Target targets/myperiph successfully set target.build_profile to optimized $ newt build myblerph Building target targets/myperiph ... Linking ~/dev/nrf52dk/bin/targets/myperiph/app/apps/bleprph/bleprph.elf Target successfully built: targets/myperiph $ newt create-image myperiph 1.0.0 App image succesfully generated: ~/dev/nrf52dk/bin/targets/myperiph/app/apps/bleprph/bleprph.img $ newt load myperiph Loading app image into slot 1 Now if you reset the board, and fire up your BLE Central App, you should see a new peripheral device called 'nimble-bleprph'. Now that you can see the device, you can begin to interact with the advertised service. Click on the device and you'll establish a connection. Now that you're connected, you can see the Services that are being advertised. Scroll to the bottom and you will see a Read Characteristic, and a Read/Write Characteristic. Just click on the Read Write Characteristic and you will see the existing value. Type in a new value. And you will see the new value reflected. If you still have your console connected, you will be able to see the connection requests, and pairing, happen on the device as well. 258894:[ts=2022609336ssb, mod=64 level=1] connection established; status=0 handle=1 our_ota_addr_type=0 our_ota_addr=0a:0a:0a:0a:0a:0a our_id_addr_type=0 our_id_addr=0a:0a:0a:0a:0a:0a peer_ota_addr_type=1 peer_ota_addr=7f:be:d4:44:c0:d4 peer_id_addr_type=1 peer_id_addr=7f:be:d4:44:c0:d4 conn_itvl=24 conn_latency=0 supervision_timeout=72 encrypted=0 authenticated=0 bonded=0 258904:[ts=2022687456ssb, mod=64 level=1] 258917:[ts=2022789012ssb, mod=64 level=1] mtu update event; conn_handle=1 cid=4 mtu=185 258925:[ts=2022851508ssb, mod=64 level=1] subscribe event; conn_handle=1 attr_handle=14 reason=1 prevn=0 curn=0 previ=0 curi=1 261486:[ts=2042859320ssb, mod=64 level=1] encryption change event; status=0 handle=1 our_ota_addr_type=0 our_ota_addr=0a:0a:0a:0a:0a:0a our_id_addr_type=0 our_id_addr=0a:0a:0a:0a:0a:0a peer_ota_addr_type=1 peer_ota_addr=7f:be:d4:44:c0:d4 peer_id_addr_type=1 peer_id_addr=7f:be:d4:44:c0:d4 conn_itvl=24 conn_latency=0 supervision_timeout=72 encrypted=1 authenticated=0 bonded=1 261496:[ts=2042937440ssb, mod=64 level=1] Congratulations! You've just built and connected your first BLE Peripheral device!","title":"Create a New Target"},{"location":"os/tutorials/bleprph/bleprph-chr-access/","text":"BLE Peripheral Project Characteristic Access Review A characteristic's access callback implements its behavior. Recall that services and characteristics are registered with NimBLE via attribute tables. Each characteristic definition in an attribute table contains an access_cb field. The access_cb field is an application callback that gets executed whenever a peer device attempts to read or write the characteristic. Earlier in this tutorial, we looked at how bleprph implements the ANS service. Let's take another look at how bleprph specifies the first few characteristics in this service. static const struct ble_gatt_svc_def gatt_svr_svcs [] = { { /*** Alert Notification Service. */ . type = BLE_GATT_SVC_TYPE_PRIMARY , . uuid128 = BLE_UUID16 ( GATT_SVR_SVC_ALERT_UUID ), . characteristics = ( struct ble_gatt_chr_def []) { { . uuid128 = BLE_UUID16 ( GATT_SVR_CHR_SUP_NEW_ALERT_CAT_UUID ), . access_cb = gatt_svr_chr_access_alert , . flags = BLE_GATT_CHR_F_READ , }, { . uuid128 = BLE_UUID16 ( GATT_SVR_CHR_NEW_ALERT ), . access_cb = gatt_svr_chr_access_alert , . flags = BLE_GATT_CHR_F_NOTIFY , }, { // [...] As you can see, bleprph uses the same access_cb function for all the ANS service characteristics, but the developer could have implemented separate functions for each characteristic if they preferred. Here is part of the access_cb function that the ANS service characteristics use: static int gatt_svr_chr_access_alert ( uint16_t conn_handle , uint16_t attr_handle , struct ble_gatt_access_ctxt *ctxt , void *arg ) { uint16_t uuid16 ; int rc ; uuid16 = ble_uuid_128_to_16 ( ctxt->chr->uuid128 ); assert ( uuid16 != 0 ); switch ( uuid16 ) { case GATT_SVR_CHR_SUP_NEW_ALERT_CAT_UUID : assert ( ctxt->op == BLE_GATT_ACCESS_OP_READ_CHR ); rc = os_mbuf_append ( ctxt->om , &gatt_svr_new_alert_cat , sizeof gatt_svr_new_alert_cat ); return rc == 0 ? 0 : BLE_ATT_ERR_INSUFFICIENT_RES ; case GATT_SVR_CHR_UNR_ALERT_STAT_UUID : if ( ctxt->op == BLE_GATT_ACCESS_OP_WRITE_CHR ) { if ( OS_MBUF_PKTLEN ( ctxt->om ) != sizeof gatt_svr_unr_alert_stat ) { return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN ; } rc = ble_hs_mbuf_to_flat ( ctxt->om , &gatt_svr_unr_alert_stat , sizeof gatt_svr_unr_alert_stat , NULL ); if ( rc != 0 ) { return BLE_ATT_ERR_UNLIKELY ; } return 0 ; /* [...] */ default : assert ( 0 ); return BLE_ATT_ERR_UNLIKELY ; } } After you've taken a moment to examine the structure of this function, let's explore some details. Function signature static int gatt_svr_chr_access_alert ( uint16_t conn_handle , uint16_t attr_handle , struct ble_gatt_access_ctxt *ctxt , void *arg ) A characteristic access function always takes this same set of parameters and always returns an int. The parameters to this function type are documented below. Parameter Purpose Notes conn_handle Indicates which connection the characteristic access was sent over. Use this value to determine which peer is accessing the characteristic. attr_handle The low-level ATT handle of the characteristic value attribute. Can be used to determine which characteristic is being accessed if you don't want to perform a UUID lookup. op Indicates whether this is a read or write operation Valid values are: BLE_GATT_ACCESS_OP_READ_CHR BLE_GATT_ACCESS_OP_WRITE_CHR ctxt Contains the characteristic value mbuf that the application needs to access. For characteristic accesses, use the ctxt->chr member; for descriptor accesses, use the ctxt->dsc member. The return value of the access function tells the NimBLE stack how to respond to the peer performing the operation. A value of 0 indicates success. For failures, the function returns the specific ATT error code that the NimBLE stack should respond with. Note: The return code is a formal code, not a NimBLE value! Determine characteristic being accessed { uint16_t uuid16 ; uuid16 = ble_uuid_128_to_16 ( ctxt->chr->uuid128 ); assert ( uuid16 != 0 ); switch ( uuid16 ) { // [...] This function uses the UUID to determine which characteristic is being accessed. There are two alternative methods bleprph could have used to accomplish this task: Map characteristics to ATT handles during service registration; use the attr_handle parameter as a key into this table during characteristic access. Implement a dedicated function for each characteristic; each function inherently knows which characteristic it corresponds to. All the ANS service characteristics have 16-bit UUIDs, so this function uses the ble_uuid_128_to_16() function to convert the 128-bit UUID to its corresponding 16-bit UUID. This conversion function returns the corresponding 16-bit UUID on success, or 0 on failure. Success is asserted here to ensure the NimBLE stack is doing its job properly; the stack should only call this function for accesses to characteristics that it is registered with, and all ANS service characteristics have valid 16-bit UUIDs. Read access case GATT_SVR_CHR_SUP_NEW_ALERT_CAT_UUID : assert ( ctxt->op == BLE_GATT_ACCESS_OP_READ_CHR ); rc = os_mbuf_append ( ctxt->om , &gatt_svr_new_alert_cat , sizeof gatt_svr_new_alert_cat ); return rc == 0 ? 0 : BLE_ATT_ERR_INSUFFICIENT_RES ; This code excerpt handles read accesses to the Supported New Alert Category characteristic. The assert() here is another case of making sure the NimBLE stack is doing its job; this characteristic was registered as read-only, so the stack should have prevented write accesses. To fulfill a characteristic read request, the application needs fill a buffer ( om ) with the characteristic value. The NimBLE host will then include the contents of this buffer in its read response. NimBLE uses mbufs to exchange data between itself and the application. To fill an mbuf with data that is available in a contiguous chunk of memory, the os_mbuf_append() function suffices. The source of the data, gatt_svr_new_alert_cat , is is stored in read-only memory as follows: static const uint8_t gatt_svr_new_alert_cat = 0x01 ; /* Simple alert. */ It is not shown in the above snippet, but this function ultimately returns 0. By returning 0, bleprph indicates that the characteristic data in ctxt->om is valid and that NimBLE should include it in its response to the peer. Write access static uint16_t gatt_svr_unr_alert_stat ; case GATT_SVR_CHR_UNR_ALERT_STAT_UUID : if ( ctxt->op == BLE_GATT_ACCESS_OP_WRITE_CHR ) { if ( OS_MBUF_PKTLEN ( ctxt->om ) != sizeof gatt_svr_unr_alert_stat ) { return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN ; } rc = ble_hs_mbuf_to_flat ( ctxt->om , &gatt_svr_unr_alert_stat , sizeof gatt_svr_unr_alert_stat , NULL ); if ( rc != 0 ) { return BLE_ATT_ERR_UNLIKELY ; } return 0 ; } else /* [...] */ This code excerpt handles writes to the New Alert characteristic. For writes, the role of the ctxt->om field is the reverse of the read case. The NimBLE stack uses these fields to indicate the data written by the peer. Many characteristics have strict length requirements for write operations. This characteristic has such a restriction; if the written data is not a 2-byte value, the application tells NimBLE to respond with an invalid attribute value length error. bleprph copies the data out of the supplied mbuf and writes it to a contiguous chunk of storage (the gatt_svr_unr_alert_stat variable). This is accomplished with the ble_hs_mbuf_to_flat() function. If the application did not have a suitable destination for the data handy, it could have inherited the mbuf from the context object. This is done by saving a copy of the mbuf pointer, and assigning NULL to ctxt->om . By assigning NULL to the mbuf pointer, your application prevents the stack from freeing the mbuf while it is still being used. Be aware, however, that it is the application's responsibility to free inherited mbufs.","title":"Characteristic Access"},{"location":"os/tutorials/bleprph/bleprph-chr-access/#ble-peripheral-project","text":"","title":"BLE Peripheral Project"},{"location":"os/tutorials/bleprph/bleprph-chr-access/#characteristic-access","text":"","title":"Characteristic Access"},{"location":"os/tutorials/bleprph/bleprph-chr-access/#review","text":"A characteristic's access callback implements its behavior. Recall that services and characteristics are registered with NimBLE via attribute tables. Each characteristic definition in an attribute table contains an access_cb field. The access_cb field is an application callback that gets executed whenever a peer device attempts to read or write the characteristic. Earlier in this tutorial, we looked at how bleprph implements the ANS service. Let's take another look at how bleprph specifies the first few characteristics in this service. static const struct ble_gatt_svc_def gatt_svr_svcs [] = { { /*** Alert Notification Service. */ . type = BLE_GATT_SVC_TYPE_PRIMARY , . uuid128 = BLE_UUID16 ( GATT_SVR_SVC_ALERT_UUID ), . characteristics = ( struct ble_gatt_chr_def []) { { . uuid128 = BLE_UUID16 ( GATT_SVR_CHR_SUP_NEW_ALERT_CAT_UUID ), . access_cb = gatt_svr_chr_access_alert , . flags = BLE_GATT_CHR_F_READ , }, { . uuid128 = BLE_UUID16 ( GATT_SVR_CHR_NEW_ALERT ), . access_cb = gatt_svr_chr_access_alert , . flags = BLE_GATT_CHR_F_NOTIFY , }, { // [...] As you can see, bleprph uses the same access_cb function for all the ANS service characteristics, but the developer could have implemented separate functions for each characteristic if they preferred. Here is part of the access_cb function that the ANS service characteristics use: static int gatt_svr_chr_access_alert ( uint16_t conn_handle , uint16_t attr_handle , struct ble_gatt_access_ctxt *ctxt , void *arg ) { uint16_t uuid16 ; int rc ; uuid16 = ble_uuid_128_to_16 ( ctxt->chr->uuid128 ); assert ( uuid16 != 0 ); switch ( uuid16 ) { case GATT_SVR_CHR_SUP_NEW_ALERT_CAT_UUID : assert ( ctxt->op == BLE_GATT_ACCESS_OP_READ_CHR ); rc = os_mbuf_append ( ctxt->om , &gatt_svr_new_alert_cat , sizeof gatt_svr_new_alert_cat ); return rc == 0 ? 0 : BLE_ATT_ERR_INSUFFICIENT_RES ; case GATT_SVR_CHR_UNR_ALERT_STAT_UUID : if ( ctxt->op == BLE_GATT_ACCESS_OP_WRITE_CHR ) { if ( OS_MBUF_PKTLEN ( ctxt->om ) != sizeof gatt_svr_unr_alert_stat ) { return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN ; } rc = ble_hs_mbuf_to_flat ( ctxt->om , &gatt_svr_unr_alert_stat , sizeof gatt_svr_unr_alert_stat , NULL ); if ( rc != 0 ) { return BLE_ATT_ERR_UNLIKELY ; } return 0 ; /* [...] */ default : assert ( 0 ); return BLE_ATT_ERR_UNLIKELY ; } } After you've taken a moment to examine the structure of this function, let's explore some details.","title":"Review"},{"location":"os/tutorials/bleprph/bleprph-chr-access/#function-signature","text":"static int gatt_svr_chr_access_alert ( uint16_t conn_handle , uint16_t attr_handle , struct ble_gatt_access_ctxt *ctxt , void *arg ) A characteristic access function always takes this same set of parameters and always returns an int. The parameters to this function type are documented below. Parameter Purpose Notes conn_handle Indicates which connection the characteristic access was sent over. Use this value to determine which peer is accessing the characteristic. attr_handle The low-level ATT handle of the characteristic value attribute. Can be used to determine which characteristic is being accessed if you don't want to perform a UUID lookup. op Indicates whether this is a read or write operation Valid values are: BLE_GATT_ACCESS_OP_READ_CHR BLE_GATT_ACCESS_OP_WRITE_CHR ctxt Contains the characteristic value mbuf that the application needs to access. For characteristic accesses, use the ctxt->chr member; for descriptor accesses, use the ctxt->dsc member. The return value of the access function tells the NimBLE stack how to respond to the peer performing the operation. A value of 0 indicates success. For failures, the function returns the specific ATT error code that the NimBLE stack should respond with. Note: The return code is a formal code, not a NimBLE value!","title":"Function signature"},{"location":"os/tutorials/bleprph/bleprph-chr-access/#determine-characteristic-being-accessed","text":"{ uint16_t uuid16 ; uuid16 = ble_uuid_128_to_16 ( ctxt->chr->uuid128 ); assert ( uuid16 != 0 ); switch ( uuid16 ) { // [...] This function uses the UUID to determine which characteristic is being accessed. There are two alternative methods bleprph could have used to accomplish this task: Map characteristics to ATT handles during service registration; use the attr_handle parameter as a key into this table during characteristic access. Implement a dedicated function for each characteristic; each function inherently knows which characteristic it corresponds to. All the ANS service characteristics have 16-bit UUIDs, so this function uses the ble_uuid_128_to_16() function to convert the 128-bit UUID to its corresponding 16-bit UUID. This conversion function returns the corresponding 16-bit UUID on success, or 0 on failure. Success is asserted here to ensure the NimBLE stack is doing its job properly; the stack should only call this function for accesses to characteristics that it is registered with, and all ANS service characteristics have valid 16-bit UUIDs.","title":"Determine characteristic being accessed"},{"location":"os/tutorials/bleprph/bleprph-chr-access/#read-access","text":"case GATT_SVR_CHR_SUP_NEW_ALERT_CAT_UUID : assert ( ctxt->op == BLE_GATT_ACCESS_OP_READ_CHR ); rc = os_mbuf_append ( ctxt->om , &gatt_svr_new_alert_cat , sizeof gatt_svr_new_alert_cat ); return rc == 0 ? 0 : BLE_ATT_ERR_INSUFFICIENT_RES ; This code excerpt handles read accesses to the Supported New Alert Category characteristic. The assert() here is another case of making sure the NimBLE stack is doing its job; this characteristic was registered as read-only, so the stack should have prevented write accesses. To fulfill a characteristic read request, the application needs fill a buffer ( om ) with the characteristic value. The NimBLE host will then include the contents of this buffer in its read response. NimBLE uses mbufs to exchange data between itself and the application. To fill an mbuf with data that is available in a contiguous chunk of memory, the os_mbuf_append() function suffices. The source of the data, gatt_svr_new_alert_cat , is is stored in read-only memory as follows: static const uint8_t gatt_svr_new_alert_cat = 0x01 ; /* Simple alert. */ It is not shown in the above snippet, but this function ultimately returns 0. By returning 0, bleprph indicates that the characteristic data in ctxt->om is valid and that NimBLE should include it in its response to the peer.","title":"Read access"},{"location":"os/tutorials/bleprph/bleprph-chr-access/#write-access","text":"static uint16_t gatt_svr_unr_alert_stat ; case GATT_SVR_CHR_UNR_ALERT_STAT_UUID : if ( ctxt->op == BLE_GATT_ACCESS_OP_WRITE_CHR ) { if ( OS_MBUF_PKTLEN ( ctxt->om ) != sizeof gatt_svr_unr_alert_stat ) { return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN ; } rc = ble_hs_mbuf_to_flat ( ctxt->om , &gatt_svr_unr_alert_stat , sizeof gatt_svr_unr_alert_stat , NULL ); if ( rc != 0 ) { return BLE_ATT_ERR_UNLIKELY ; } return 0 ; } else /* [...] */ This code excerpt handles writes to the New Alert characteristic. For writes, the role of the ctxt->om field is the reverse of the read case. The NimBLE stack uses these fields to indicate the data written by the peer. Many characteristics have strict length requirements for write operations. This characteristic has such a restriction; if the written data is not a 2-byte value, the application tells NimBLE to respond with an invalid attribute value length error. bleprph copies the data out of the supplied mbuf and writes it to a contiguous chunk of storage (the gatt_svr_unr_alert_stat variable). This is accomplished with the ble_hs_mbuf_to_flat() function. If the application did not have a suitable destination for the data handy, it could have inherited the mbuf from the context object. This is done by saving a copy of the mbuf pointer, and assigning NULL to ctxt->om . By assigning NULL to the mbuf pointer, your application prevents the stack from freeing the mbuf while it is still being used. Be aware, however, that it is the application's responsibility to free inherited mbufs.","title":"Write access"},{"location":"os/tutorials/bleprph/bleprph-gap-event/","text":"BLE Peripheral Project GAP Event callbacks Overview Every BLE connection has a GAP event callback associated with it. A GAP event callback is a bit of application code which NimBLE uses to inform you of connection-related events. For example, if a connection is terminated, NimBLE lets you know about it with a call to that connection's callback. In the advertising section of this tutorial, we saw how the application specifies a GAP event callback when it begins advertising. NimBLE uses this callback to notify the application that a central has connected to your peripheral after receiving an advertisement. Let's revisit how bleprph specifies its connection callback when advertising: /* Begin advertising. */ memset ( &adv_params , 0 , sizeof adv_params ); adv_params . conn_mode = BLE_GAP_CONN_MODE_UND ; adv_params . disc_mode = BLE_GAP_DISC_MODE_GEN ; rc = ble_gap_adv_start ( BLE_ADDR_TYPE_PUBLIC , 0 , NULL , BLE_HS_FOREVER , &adv_params , bleprph_gap_event , NULL ); if ( rc != 0 ) { BLEPRPH_LOG ( ERROR , \"error enabling advertisement; rc=%d\\n\" , rc ); return ; } bleprph_gap_event() The bleprph_gap_event() function is bleprph 's GAP event callback; NimBLE calls this function when the advertising operation leads to connection establishment. Upon connection establishment, this callback becomes permanently associated with the connection; all subsequent events related to this connection are communicated through this callback. Now let's look at the function that bleprph uses for all its connection callbacks: bleprph_gap_event() . /** * The nimble host executes this callback when a GAP event occurs. The * application associates a GAP event callback with each connection that forms. * bleprph uses the same callback for all connections. * * @param event The type of event being signalled. * @param ctxt Various information pertaining to the event. * @param arg Application-specified argument; unuesd by * bleprph. * * @return 0 if the application successfully handled the * event; nonzero on failure. The semantics * of the return code is specific to the * particular GAP event being signalled. */ static int bleprph_gap_event ( struct ble_gap_event *event , void *arg ) { struct ble_gap_conn_desc desc ; int rc ; switch ( event->type ) { case BLE_GAP_EVENT_CONNECT : /* A new connection was established or a connection attempt failed. */ BLEPRPH_LOG ( INFO , \"connection %s; status=%d \" , event->connect . status == 0 ? \"established\" : \"failed\" , event->connect . status ); if ( event->connect . status == 0 ) { rc = ble_gap_conn_find ( event->connect . conn_handle , &desc ); assert ( rc == 0 ); bleprph_print_conn_desc ( &desc ); } BLEPRPH_LOG ( INFO , \"\\n\" ); if ( event->connect . status != 0 ) { /* Connection failed; resume advertising. */ bleprph_advertise (); } return 0 ; case BLE_GAP_EVENT_DISCONNECT : BLEPRPH_LOG ( INFO , \"disconnect; reason=%d \" , event->disconnect . reason ); bleprph_print_conn_desc ( &event->disconnect . conn ); BLEPRPH_LOG ( INFO , \"\\n\" ); /* Connection terminated; resume advertising. */ bleprph_advertise (); return 0 ; case BLE_GAP_EVENT_CONN_UPDATE : /* The central has updated the connection parameters. */ BLEPRPH_LOG ( INFO , \"connection updated; status=%d \" , event->conn_update . status ); rc = ble_gap_conn_find ( event->connect . conn_handle , &desc ); assert ( rc == 0 ); bleprph_print_conn_desc ( &desc ); BLEPRPH_LOG ( INFO , \"\\n\" ); return 0 ; case BLE_GAP_EVENT_ENC_CHANGE : /* Encryption has been enabled or disabled for this connection. */ BLEPRPH_LOG ( INFO , \"encryption change event; status=%d \" , event->enc_change . status ); rc = ble_gap_conn_find ( event->connect . conn_handle , &desc ); assert ( rc == 0 ); bleprph_print_conn_desc ( &desc ); BLEPRPH_LOG ( INFO , \"\\n\" ); return 0 ; case BLE_GAP_EVENT_SUBSCRIBE : BLEPRPH_LOG ( INFO , \"subscribe event; conn_handle=%d attr_handle=%d \" \"reason=%d prevn=%d curn=%d previ=%d curi=%d\\n\" , event->subscribe . conn_handle , event->subscribe . attr_handle , event->subscribe . reason , event->subscribe . prev_notify , event->subscribe . cur_notify , event->subscribe . prev_indicate , event->subscribe . cur_indicate ); return 0 ; } return 0 ; } Connection callbacks are used to communicate a variety of events related to a connection. An application determines the type of event that occurred by inspecting the value of the event->type parameter. The full list of event codes can be found on the GAP events page. Guarantees It is important to know what your application code is allowed to do from within a connection callback. No restrictions on NimBLE operations Your app is free to make calls into the NimBLE stack from within a connection callback. bleprph takes advantage of this freedom when it resumes advertising upon connection termination. All other NimBLE operations are also allowed (service discovery, pairing initiation, etc). All context data is transient Pointers in the context object point to data living on the stack. Your callback is free to read (or write, if appropriate) through these pointers, but you should not store these pointers for later use. If your application needs to retain some data from a context object, it needs to make a copy.","title":"GAP Event Callbacks"},{"location":"os/tutorials/bleprph/bleprph-gap-event/#ble-peripheral-project","text":"","title":"BLE Peripheral Project"},{"location":"os/tutorials/bleprph/bleprph-gap-event/#gap-event-callbacks","text":"","title":"GAP Event callbacks"},{"location":"os/tutorials/bleprph/bleprph-gap-event/#overview","text":"Every BLE connection has a GAP event callback associated with it. A GAP event callback is a bit of application code which NimBLE uses to inform you of connection-related events. For example, if a connection is terminated, NimBLE lets you know about it with a call to that connection's callback. In the advertising section of this tutorial, we saw how the application specifies a GAP event callback when it begins advertising. NimBLE uses this callback to notify the application that a central has connected to your peripheral after receiving an advertisement. Let's revisit how bleprph specifies its connection callback when advertising: /* Begin advertising. */ memset ( &adv_params , 0 , sizeof adv_params ); adv_params . conn_mode = BLE_GAP_CONN_MODE_UND ; adv_params . disc_mode = BLE_GAP_DISC_MODE_GEN ; rc = ble_gap_adv_start ( BLE_ADDR_TYPE_PUBLIC , 0 , NULL , BLE_HS_FOREVER , &adv_params , bleprph_gap_event , NULL ); if ( rc != 0 ) { BLEPRPH_LOG ( ERROR , \"error enabling advertisement; rc=%d\\n\" , rc ); return ; }","title":"Overview"},{"location":"os/tutorials/bleprph/bleprph-gap-event/#bleprph_gap_event","text":"The bleprph_gap_event() function is bleprph 's GAP event callback; NimBLE calls this function when the advertising operation leads to connection establishment. Upon connection establishment, this callback becomes permanently associated with the connection; all subsequent events related to this connection are communicated through this callback. Now let's look at the function that bleprph uses for all its connection callbacks: bleprph_gap_event() . /** * The nimble host executes this callback when a GAP event occurs. The * application associates a GAP event callback with each connection that forms. * bleprph uses the same callback for all connections. * * @param event The type of event being signalled. * @param ctxt Various information pertaining to the event. * @param arg Application-specified argument; unuesd by * bleprph. * * @return 0 if the application successfully handled the * event; nonzero on failure. The semantics * of the return code is specific to the * particular GAP event being signalled. */ static int bleprph_gap_event ( struct ble_gap_event *event , void *arg ) { struct ble_gap_conn_desc desc ; int rc ; switch ( event->type ) { case BLE_GAP_EVENT_CONNECT : /* A new connection was established or a connection attempt failed. */ BLEPRPH_LOG ( INFO , \"connection %s; status=%d \" , event->connect . status == 0 ? \"established\" : \"failed\" , event->connect . status ); if ( event->connect . status == 0 ) { rc = ble_gap_conn_find ( event->connect . conn_handle , &desc ); assert ( rc == 0 ); bleprph_print_conn_desc ( &desc ); } BLEPRPH_LOG ( INFO , \"\\n\" ); if ( event->connect . status != 0 ) { /* Connection failed; resume advertising. */ bleprph_advertise (); } return 0 ; case BLE_GAP_EVENT_DISCONNECT : BLEPRPH_LOG ( INFO , \"disconnect; reason=%d \" , event->disconnect . reason ); bleprph_print_conn_desc ( &event->disconnect . conn ); BLEPRPH_LOG ( INFO , \"\\n\" ); /* Connection terminated; resume advertising. */ bleprph_advertise (); return 0 ; case BLE_GAP_EVENT_CONN_UPDATE : /* The central has updated the connection parameters. */ BLEPRPH_LOG ( INFO , \"connection updated; status=%d \" , event->conn_update . status ); rc = ble_gap_conn_find ( event->connect . conn_handle , &desc ); assert ( rc == 0 ); bleprph_print_conn_desc ( &desc ); BLEPRPH_LOG ( INFO , \"\\n\" ); return 0 ; case BLE_GAP_EVENT_ENC_CHANGE : /* Encryption has been enabled or disabled for this connection. */ BLEPRPH_LOG ( INFO , \"encryption change event; status=%d \" , event->enc_change . status ); rc = ble_gap_conn_find ( event->connect . conn_handle , &desc ); assert ( rc == 0 ); bleprph_print_conn_desc ( &desc ); BLEPRPH_LOG ( INFO , \"\\n\" ); return 0 ; case BLE_GAP_EVENT_SUBSCRIBE : BLEPRPH_LOG ( INFO , \"subscribe event; conn_handle=%d attr_handle=%d \" \"reason=%d prevn=%d curn=%d previ=%d curi=%d\\n\" , event->subscribe . conn_handle , event->subscribe . attr_handle , event->subscribe . reason , event->subscribe . prev_notify , event->subscribe . cur_notify , event->subscribe . prev_indicate , event->subscribe . cur_indicate ); return 0 ; } return 0 ; } Connection callbacks are used to communicate a variety of events related to a connection. An application determines the type of event that occurred by inspecting the value of the event->type parameter. The full list of event codes can be found on the GAP events page.","title":"bleprph_gap_event()"},{"location":"os/tutorials/bleprph/bleprph-gap-event/#guarantees","text":"It is important to know what your application code is allowed to do from within a connection callback. No restrictions on NimBLE operations Your app is free to make calls into the NimBLE stack from within a connection callback. bleprph takes advantage of this freedom when it resumes advertising upon connection termination. All other NimBLE operations are also allowed (service discovery, pairing initiation, etc). All context data is transient Pointers in the context object point to data living on the stack. Your callback is free to read (or write, if appropriate) through these pointers, but you should not store these pointers for later use. If your application needs to retain some data from a context object, it needs to make a copy.","title":"Guarantees"},{"location":"os/tutorials/bleprph/bleprph-intro/","text":"BLE Peripheral Project Introduction Overview bleprph is an example app included in the apache-mynewt-core repository. This app implements a simple BLE peripheral with the following properties: Supports a single concurrent connection. Automatically advertises connectability when not connected to a central device. Supports pairing and bonding. Supports five services. This tutorial aims to provide a guided tour through the bleprph app source code. This document builds on some concepts described elsewhere in the Apache Mynewt documentation. Before proceeding with this tutorial, you might want to familiarize yourself with the following pages: Create Your First Mynewt Project NimBLE Stack Initialization Services, Characteristics, Descriptors A BLE peripheral interfaces with other BLE devices by exposing services , characteristics , and descriptors . All three of these entities are implemented at a lower layer via attributes . If you are not familiar with these concepts, you will probably want to check out this overview from the Bluetooth Developer's site before proceeding. Now let's dig in to some C code.","title":"toc"},{"location":"os/tutorials/bleprph/bleprph-intro/#ble-peripheral-project","text":"","title":"BLE Peripheral Project"},{"location":"os/tutorials/bleprph/bleprph-intro/#introduction","text":"","title":"Introduction"},{"location":"os/tutorials/bleprph/bleprph-intro/#overview","text":"bleprph is an example app included in the apache-mynewt-core repository. This app implements a simple BLE peripheral with the following properties: Supports a single concurrent connection. Automatically advertises connectability when not connected to a central device. Supports pairing and bonding. Supports five services. This tutorial aims to provide a guided tour through the bleprph app source code. This document builds on some concepts described elsewhere in the Apache Mynewt documentation. Before proceeding with this tutorial, you might want to familiarize yourself with the following pages: Create Your First Mynewt Project NimBLE Stack Initialization","title":"Overview"},{"location":"os/tutorials/bleprph/bleprph-intro/#services-characteristics-descriptors","text":"A BLE peripheral interfaces with other BLE devices by exposing services , characteristics , and descriptors . All three of these entities are implemented at a lower layer via attributes . If you are not familiar with these concepts, you will probably want to check out this overview from the Bluetooth Developer's site before proceeding. Now let's dig in to some C code.","title":"Services, Characteristics, Descriptors"},{"location":"os/tutorials/bleprph/bleprph-svc-reg/","text":"BLE Peripheral Project Service Registration Attribute Set The NimBLE host uses a table-based design for GATT server configuration. The set of supported attributes are expressed as a series of tables that resides in your C code. bleprph supports the following services: GAP GATT newtmgr Alert Notification Security Test The first two services (GAP and GATT) are mandatory services that all BLE peripherals must support. These are implemented in a separate package which the bleprph app depends on. Later, we will see how the main() function initializes and registers this package. Your app will follow the same procedure when using GATT service libraries. The third service, newtmgr, is vendor-specific service supported by most Mynewt devices. This service is used for remote configuration, status queries, and firmware updates. As with GAP and GATT, this service is implemented in a package separate from the bleprph app. The final two services, Alert Notification and Security Test , are not implemented in separate libraries. Rather, these services are specific to the app, so they are implemented the bleprph app itself. The attribute table used to express these services is located in the gatt_svr.c file, so let's take a look at that now. The attribute table is called gatt_svr_svcs ; here are the first several lines from this table: static const struct ble_gatt_svc_def gatt_svr_svcs [] = { { /*** Alert Notification Service. */ . type = BLE_GATT_SVC_TYPE_PRIMARY , . uuid128 = BLE_UUID16 ( GATT_SVR_SVC_ALERT_UUID ), . characteristics = ( struct ble_gatt_chr_def []) { { . uuid128 = BLE_UUID16 ( GATT_SVR_CHR_SUP_NEW_ALERT_CAT_UUID ), . access_cb = gatt_svr_chr_access_alert , . flags = BLE_GATT_CHR_F_READ , }, { . uuid128 = BLE_UUID16 ( GATT_SVR_CHR_NEW_ALERT ), . access_cb = gatt_svr_chr_access_alert , . flags = BLE_GATT_CHR_F_NOTIFY , }, { // [...] As you can see, the table is an array of service definitions ( struct ble_gatt_svc_def ). This code excerpt contains a small part of the Alert Notification service. Let's now consider the contents of this table in more detail. A service definition consists of the following fields: Field Meaning Notes type Specifies whether this is a primary or secondary service. Secondary services are not very common. When in doubt, specify BLE_GATT_SVC_TYPE_PRIMARY for new services. uuid128 The 128-bit UUID of this service. If the service has a 16-bit UUID, you can convert it to its corresponding 128-bit UUID with the BLE_UUID16() macro. characteristics The array of characteristics that belong to this service. A service is little more than a container of characteristics; the characteristics themselves are where the real action happens. A characteristic definition consists of the following fields: Field Meaning Notes uuid128 The 128-bit UUID of this characteristic. If the characteristic has a 16-bit UUID, you can convert it to its corresponding 128-bit UUID with the BLE_UUID16() macro. access_cb A callback function that gets executed whenever a peer device accesses this characteristic. For reads: this function generates the value that gets sent back to the peer. For writes: this function receives the written value as an argument. flags Indicates which operations are permitted for this characteristic. The NimBLE stack responds negatively when a peer attempts an unsupported operation. The full list of flags can be found under ble_gatt_chr_flags in net/nimble/host/include/host/ble_gatt.h . A characteristic's access callback implements its behavior. Access callbacks are described in detail in the next section: BLE Peripheral - Characteristic Access . The service definition array and each characteristic definition array is terminated with an empty entry, represented with a 0. The below code listing shows the last service in the array, including terminating zeros for the characteristic array and service array. { /*** Service: Security test. */ . type = BLE_GATT_SVC_TYPE_PRIMARY , . uuid128 = gatt_svr_svc_sec_test_uuid , . characteristics = ( struct ble_gatt_chr_def []) { { /*** Characteristic: Random number generator. */ . uuid128 = gatt_svr_chr_sec_test_rand_uuid , . access_cb = gatt_svr_chr_access_sec_test , . flags = BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_READ_ENC , }, { /*** Characteristic: Static value. */ . uuid128 = gatt_svr_chr_sec_test_static_uuid , . access_cb = gatt_svr_chr_access_sec_test , . flags = BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_WRITE | BLE_GATT_CHR_F_WRITE_ENC , }, { 0 , /* No more characteristics in this service. */ } }, }, { 0 , /* No more services. */ }, Registration function After you have created your service table, your app needs to register it with the NimBLE stack. This is done by calling the ble_gatts_add_svcs() function. There is a small complication, though. The NimBLE host needs to allocate sufficient resources upfront to accommodate all of your peripheral's services. You can ensure your GATT services are accounted for in the host configuration object by calling the ble_gatts_count_cfg() function. The bleprph app registers its services in gatt_svr.c as follows: int gatt_svr_init ( struct ble_hs_cfg *cfg ) { int rc ; rc = ble_gatts_count_cfg ( gatt_svr_svcs , cfg ); if ( rc != 0 ) { return rc ; } rc = ble_gatts_add_svcs ( gatt_svr_svcs ); if ( rc != 0 ) { return rc ; } return 0 ; } You application will perform the above two-step process for each service definition array that you wish to register. Libraries that implement GATT services will generally expose an initialization function which does this for you. Descriptors and Included Services Your peripheral can also expose descriptors and included services. These are less common, so they are not covered in this tutorial. For more information, see the BLE User Guide .","title":"Service Registration"},{"location":"os/tutorials/bleprph/bleprph-svc-reg/#ble-peripheral-project","text":"","title":"BLE Peripheral Project"},{"location":"os/tutorials/bleprph/bleprph-svc-reg/#service-registration","text":"","title":"Service Registration"},{"location":"os/tutorials/bleprph/bleprph-svc-reg/#attribute-set","text":"The NimBLE host uses a table-based design for GATT server configuration. The set of supported attributes are expressed as a series of tables that resides in your C code. bleprph supports the following services: GAP GATT newtmgr Alert Notification Security Test The first two services (GAP and GATT) are mandatory services that all BLE peripherals must support. These are implemented in a separate package which the bleprph app depends on. Later, we will see how the main() function initializes and registers this package. Your app will follow the same procedure when using GATT service libraries. The third service, newtmgr, is vendor-specific service supported by most Mynewt devices. This service is used for remote configuration, status queries, and firmware updates. As with GAP and GATT, this service is implemented in a package separate from the bleprph app. The final two services, Alert Notification and Security Test , are not implemented in separate libraries. Rather, these services are specific to the app, so they are implemented the bleprph app itself. The attribute table used to express these services is located in the gatt_svr.c file, so let's take a look at that now. The attribute table is called gatt_svr_svcs ; here are the first several lines from this table: static const struct ble_gatt_svc_def gatt_svr_svcs [] = { { /*** Alert Notification Service. */ . type = BLE_GATT_SVC_TYPE_PRIMARY , . uuid128 = BLE_UUID16 ( GATT_SVR_SVC_ALERT_UUID ), . characteristics = ( struct ble_gatt_chr_def []) { { . uuid128 = BLE_UUID16 ( GATT_SVR_CHR_SUP_NEW_ALERT_CAT_UUID ), . access_cb = gatt_svr_chr_access_alert , . flags = BLE_GATT_CHR_F_READ , }, { . uuid128 = BLE_UUID16 ( GATT_SVR_CHR_NEW_ALERT ), . access_cb = gatt_svr_chr_access_alert , . flags = BLE_GATT_CHR_F_NOTIFY , }, { // [...] As you can see, the table is an array of service definitions ( struct ble_gatt_svc_def ). This code excerpt contains a small part of the Alert Notification service. Let's now consider the contents of this table in more detail. A service definition consists of the following fields: Field Meaning Notes type Specifies whether this is a primary or secondary service. Secondary services are not very common. When in doubt, specify BLE_GATT_SVC_TYPE_PRIMARY for new services. uuid128 The 128-bit UUID of this service. If the service has a 16-bit UUID, you can convert it to its corresponding 128-bit UUID with the BLE_UUID16() macro. characteristics The array of characteristics that belong to this service. A service is little more than a container of characteristics; the characteristics themselves are where the real action happens. A characteristic definition consists of the following fields: Field Meaning Notes uuid128 The 128-bit UUID of this characteristic. If the characteristic has a 16-bit UUID, you can convert it to its corresponding 128-bit UUID with the BLE_UUID16() macro. access_cb A callback function that gets executed whenever a peer device accesses this characteristic. For reads: this function generates the value that gets sent back to the peer. For writes: this function receives the written value as an argument. flags Indicates which operations are permitted for this characteristic. The NimBLE stack responds negatively when a peer attempts an unsupported operation. The full list of flags can be found under ble_gatt_chr_flags in net/nimble/host/include/host/ble_gatt.h . A characteristic's access callback implements its behavior. Access callbacks are described in detail in the next section: BLE Peripheral - Characteristic Access . The service definition array and each characteristic definition array is terminated with an empty entry, represented with a 0. The below code listing shows the last service in the array, including terminating zeros for the characteristic array and service array. { /*** Service: Security test. */ . type = BLE_GATT_SVC_TYPE_PRIMARY , . uuid128 = gatt_svr_svc_sec_test_uuid , . characteristics = ( struct ble_gatt_chr_def []) { { /*** Characteristic: Random number generator. */ . uuid128 = gatt_svr_chr_sec_test_rand_uuid , . access_cb = gatt_svr_chr_access_sec_test , . flags = BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_READ_ENC , }, { /*** Characteristic: Static value. */ . uuid128 = gatt_svr_chr_sec_test_static_uuid , . access_cb = gatt_svr_chr_access_sec_test , . flags = BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_WRITE | BLE_GATT_CHR_F_WRITE_ENC , }, { 0 , /* No more characteristics in this service. */ } }, }, { 0 , /* No more services. */ },","title":"Attribute Set"},{"location":"os/tutorials/bleprph/bleprph-svc-reg/#registration-function","text":"After you have created your service table, your app needs to register it with the NimBLE stack. This is done by calling the ble_gatts_add_svcs() function. There is a small complication, though. The NimBLE host needs to allocate sufficient resources upfront to accommodate all of your peripheral's services. You can ensure your GATT services are accounted for in the host configuration object by calling the ble_gatts_count_cfg() function. The bleprph app registers its services in gatt_svr.c as follows: int gatt_svr_init ( struct ble_hs_cfg *cfg ) { int rc ; rc = ble_gatts_count_cfg ( gatt_svr_svcs , cfg ); if ( rc != 0 ) { return rc ; } rc = ble_gatts_add_svcs ( gatt_svr_svcs ); if ( rc != 0 ) { return rc ; } return 0 ; } You application will perform the above two-step process for each service definition array that you wish to register. Libraries that implement GATT services will generally expose an initialization function which does this for you.","title":"Registration function"},{"location":"os/tutorials/bleprph/bleprph-svc-reg/#descriptors-and-included-services","text":"Your peripheral can also expose descriptors and included services. These are less common, so they are not covered in this tutorial. For more information, see the BLE User Guide .","title":"Descriptors and Included Services"},{"location":"os/tutorials/repo/add_repos/","text":"Adding Repositories to your Project What is a Repository A repository is a version-ed Mynewt project, which is a collection of Mynewt packages organized in a specific way for redistribution. What differentiates a repository from a Mynewt project is the presence of a repository.yml file describing the repository. This will be described below. For a basic understanding of repositories you may read the Newt Tool Manual and How to create repos . Note: For the remainder of this document we'll use the term repo as shorthand for a Mynewt repository. Repos are useful because they are an organized way for the community to share Mynewt packages and projects. In fact, the Mynewt-core is distributed as a repo. Why does Mynewt need additional repos? Repos add functionality not included in the Mynewt core. New repos might be created for several reasons. Expertise . Individuals or organizations may have expertise that they want to share in the form of repos. For example a chip vendor may create a repo to hold the Mynewt support for their chips. Non-Core component . Some components, although very useful to Mynewt users are not core to all Mynewt users. These are likely candidates to be held in different repos. Software licensing . Some software have licenses that make them incompatible with the ASF (Apache Software Foundation) license policies. These may be valuable components to some Mynewt users, but cannot be contained in the apache-Mynewt-core . What Repos are in my Project The list of repos used by your project are contained within the project.yml file. An example can be seen by creating a new project: $ mkdir ~/dev $ cd ~/dev $ newt new myproj $ cd myproj View the project.yml section and you will see a line describing the repos: project.repositories: - apache-Mynewt-core By default, this newly created project uses a single repo called apache-Mynewt-core . If you wish to add additional repos, you would add additional lines to the project.repositories variable like this. project.repositories: - apache-Mynewt-core - another_repo_named_x Repo Descriptors In addition to the repo name, the project.yml file must also contain a repo descriptor for each repository you include that gives newt information on obtaining the repo. In the same myproj above you will see the following repo descriptor. repository.apache-Mynewt-core: type: github vers: 1-latest user: apache repo: incubator-mynewt-core A repo descriptor starts with repository.<name>. . In this example, the descriptor specifies the information for the apache-Mynewt-core . The fields within the descriptor have the following definitions: type -- The type of code storage the repo uses. The current version of newt only supports github. Future versions may support generic git or other code storage mechanisms. vers -- The version of the repo to use for your project. A source code repository contains many versions of the source. This field is used to specify the one to use for this project. See the section on versions below for a detailed description of the format of this field. user -- The username for the repo. On github, this is the name after github.com in the repo path. Consider the repository https://github.com/apache/incubator-mynewt-core . It has username apache . repo -- The name of the repo. On github, this is the name after the username described above. Consider the repository https://github.com/apache/incubator-mynewt-core . It has path incubator-mynewt-core . This is a path to the source control and should not be confused with the name of the repo that you used in the repository.<name> declaration above. That name is contained elsewhere within the repo. See Below. Adding Existing Repos to my Project To add a new repo to your project, you have to complete two steps. Edit the project.yml file and add a new repo descriptor. The previous section includes information on the field required in your repo descriptor. Edit the project/yml file and add a new line to the project.repositories variable with the name of the repo you are adding. An example of a project.yml file with two repositories is shown below: project.name: \"my_project\" project.repositories: - apache-Mynewt-core - Mynewt_arduino_zero # Use github's distribution mechanism for core ASF libraries. # This provides mirroring automatically for us. # repository.apache-Mynewt-core: type: github vers: 1-latest user: apache repo: incubator-mynewt-core # a special repo to hold hardware specific stuff for arduino zero repository.Mynewt_arduino_zero: type: github vers: 1-latest user: runtimeco repo: Mynewt_arduino_zero What Version of the Repo to use Mynewt repos are version-ed artifacts. They are stored in source control systems like github. The repo descriptor in your project.yml file must specify the version of the repo you will accept into your project. For now, we are at the beginnings of Mynewt. For testing and evaluation please use 1-latest in the vers field in your repo descriptor. vers:1-latest See Create a Repo for a description of the versioning system and all the possible ways to specify a version to use. Identifying a Repo A repo contains Mynewt packages organized in a specific way and stored in one of the supported code storage methods described above. In other words, it is a Mynewt project with an additional file repository.yml which describes the repo for use by newt (and humans browsing them). It contains a mapping of version numbers to the actual github branches containing the source code. Note that the repository.yml file lives only in the master branch of the git repository. Newt will always fetch this file from the master branch and then use that to determine the actual branch required depending on the version specified in your project.yml file. Special care should be taken to ensure that this file exists only in the master branch. Here is the repository.yml file from the apache-Mynewt-core: repo.name: apache-mynewt-core repo.versions: \"0.0.0\": \"master\" \"0.0.1\": \"master\" \"0.7.9\": \"mynewt_0_8_0_b2_tag\" \"0.8.0\": \"mynewt_0_8_0_tag\" \"0.9.0\": \"mynewt_0_9_0_tag\" \"0.9.9\": \"mynewt_1_0_0_b1_tag\" \"0.9.99\": \"mynewt_1_0_0_b2_tag\" \"0.9.999\": \"mynewt_1_0_0_rc1_tag\" \"1.0.0\": \"mynewt_1_0_0_tag\" \"0-latest\": \"1.0.0\" # 1.0.0 \"0-dev\": \"0.0.0\" # master \"0.8-latest\": \"0.8.0\" \"0.9-latest\": \"0.9.0\" \"1.0-latest\": \"1.0.0\" # 1.0.0 It contains the following: repo.name The external name that is used to include the library in your project.yml file. This is the name you in include in the project.repositories variable when adding this repository to your project. repo.versions A description of what versions to give the user depending on the settings in their project.yml file. Repo Version The repo version number resolves to an actual git branch depending on the mapping specified in repository.yml for that repo. The version field argument in your project.yml file supports multiple formats for flexibility: <major_num>.<minor_num>.<revision_num> or <major_num>.<minor_num>-<stability string> or <major_num>-<stability string> The stability string can be one of 3 pre-defined stability values. stable -- A stable release version of the repository dev -- A development version from the repository latest -- The latest from the repository In your project.yml file you can specify different combinations of the version number and stability value. For example: 1-latest -- The latest version with major number 1 1.2-stable -- The latest stable version with major and minor number 1.2 1.2-dev -- The development version from 1.2 1.1.1 -- a specific version 1.1.1 You cannot specify a stability string with a fully numbered version, e.g. 1.2.8-stable Repo Versions Available A repository.yml file contains information to match a version request into a git branch to fetch for your project. It's up to the repository maintainer to map these to branches of the repository. For example, let's say in a fictitious repository the following are defined. repo.versions: \"0.8.0\": \"xxx_branch_0_8_0\" \"1.0.0\": \"xxx_branch_1_0_0\" \"1.0.2\": \"xxx_branch_1_0_2\" \"1.1.1\": \"xxx_branch_1_1_0\" \"1.1.2\": \"xxx_branch_1_1_2\" \"1.2.0\": \"xxx_branch_1_2_0\" \"1.2.1\": \"xxx_branch_1_2_1\" \"1.2-dev\": \"1.2.1\" \"1-dev\": \"1.2-dev\" \"1.2-stable\": \"1.2.0\" \"0-latest\": \"0.8.0\" \"1-latest\": \"1-dev\" .... When the project.yml file asks for 1.2-stable it is resolved to version 1.2.0 (perhaps 1.2.1 is not stable yet), which in turn resolves to a specific branch xxx_branch_1_2_0 . This is the branch that newt fetches into your project. Note: Make sure a repo version exists in the repository.yml file of a repo you wish to add. Otherwise Newt will not be able to resolve the version and will fail to fetch the repo into your project. How to find out what Repos are available for Mynewt components Currently, there is no newt command to locate/search Mynewt package repositories. However, since the newt tool supports only github, searching github by keyword is a satisfactory option until a search tool is created. When searching github, recall that a Mynewt repository must have a repository.yml file in its root directory. If you don't see that file, it's not a Mynewt repository and can't be included in your project via the newt tool. Once you find a repository, the github URL and repository.yml file should give you all the information to add it to your project.yml file.","title":"toc"},{"location":"os/tutorials/repo/add_repos/#adding-repositories-to-your-project","text":"","title":"Adding Repositories to your Project"},{"location":"os/tutorials/repo/add_repos/#what-is-a-repository","text":"A repository is a version-ed Mynewt project, which is a collection of Mynewt packages organized in a specific way for redistribution. What differentiates a repository from a Mynewt project is the presence of a repository.yml file describing the repository. This will be described below. For a basic understanding of repositories you may read the Newt Tool Manual and How to create repos . Note: For the remainder of this document we'll use the term repo as shorthand for a Mynewt repository. Repos are useful because they are an organized way for the community to share Mynewt packages and projects. In fact, the Mynewt-core is distributed as a repo.","title":"What is a Repository"},{"location":"os/tutorials/repo/add_repos/#why-does-mynewt-need-additional-repos","text":"Repos add functionality not included in the Mynewt core. New repos might be created for several reasons. Expertise . Individuals or organizations may have expertise that they want to share in the form of repos. For example a chip vendor may create a repo to hold the Mynewt support for their chips. Non-Core component . Some components, although very useful to Mynewt users are not core to all Mynewt users. These are likely candidates to be held in different repos. Software licensing . Some software have licenses that make them incompatible with the ASF (Apache Software Foundation) license policies. These may be valuable components to some Mynewt users, but cannot be contained in the apache-Mynewt-core .","title":"Why does Mynewt need additional repos?"},{"location":"os/tutorials/repo/add_repos/#what-repos-are-in-my-project","text":"The list of repos used by your project are contained within the project.yml file. An example can be seen by creating a new project: $ mkdir ~/dev $ cd ~/dev $ newt new myproj $ cd myproj View the project.yml section and you will see a line describing the repos: project.repositories: - apache-Mynewt-core By default, this newly created project uses a single repo called apache-Mynewt-core . If you wish to add additional repos, you would add additional lines to the project.repositories variable like this. project.repositories: - apache-Mynewt-core - another_repo_named_x","title":"What Repos are in my Project"},{"location":"os/tutorials/repo/add_repos/#repo-descriptors","text":"In addition to the repo name, the project.yml file must also contain a repo descriptor for each repository you include that gives newt information on obtaining the repo. In the same myproj above you will see the following repo descriptor. repository.apache-Mynewt-core: type: github vers: 1-latest user: apache repo: incubator-mynewt-core A repo descriptor starts with repository.<name>. . In this example, the descriptor specifies the information for the apache-Mynewt-core . The fields within the descriptor have the following definitions: type -- The type of code storage the repo uses. The current version of newt only supports github. Future versions may support generic git or other code storage mechanisms. vers -- The version of the repo to use for your project. A source code repository contains many versions of the source. This field is used to specify the one to use for this project. See the section on versions below for a detailed description of the format of this field. user -- The username for the repo. On github, this is the name after github.com in the repo path. Consider the repository https://github.com/apache/incubator-mynewt-core . It has username apache . repo -- The name of the repo. On github, this is the name after the username described above. Consider the repository https://github.com/apache/incubator-mynewt-core . It has path incubator-mynewt-core . This is a path to the source control and should not be confused with the name of the repo that you used in the repository.<name> declaration above. That name is contained elsewhere within the repo. See Below.","title":"Repo Descriptors"},{"location":"os/tutorials/repo/add_repos/#adding-existing-repos-to-my-project","text":"To add a new repo to your project, you have to complete two steps. Edit the project.yml file and add a new repo descriptor. The previous section includes information on the field required in your repo descriptor. Edit the project/yml file and add a new line to the project.repositories variable with the name of the repo you are adding. An example of a project.yml file with two repositories is shown below: project.name: \"my_project\" project.repositories: - apache-Mynewt-core - Mynewt_arduino_zero # Use github's distribution mechanism for core ASF libraries. # This provides mirroring automatically for us. # repository.apache-Mynewt-core: type: github vers: 1-latest user: apache repo: incubator-mynewt-core # a special repo to hold hardware specific stuff for arduino zero repository.Mynewt_arduino_zero: type: github vers: 1-latest user: runtimeco repo: Mynewt_arduino_zero","title":"Adding Existing Repos to my Project"},{"location":"os/tutorials/repo/add_repos/#what-version-of-the-repo-to-use","text":"Mynewt repos are version-ed artifacts. They are stored in source control systems like github. The repo descriptor in your project.yml file must specify the version of the repo you will accept into your project. For now, we are at the beginnings of Mynewt. For testing and evaluation please use 1-latest in the vers field in your repo descriptor. vers:1-latest See Create a Repo for a description of the versioning system and all the possible ways to specify a version to use.","title":"What Version of the Repo to use"},{"location":"os/tutorials/repo/add_repos/#identifying-a-repo","text":"A repo contains Mynewt packages organized in a specific way and stored in one of the supported code storage methods described above. In other words, it is a Mynewt project with an additional file repository.yml which describes the repo for use by newt (and humans browsing them). It contains a mapping of version numbers to the actual github branches containing the source code. Note that the repository.yml file lives only in the master branch of the git repository. Newt will always fetch this file from the master branch and then use that to determine the actual branch required depending on the version specified in your project.yml file. Special care should be taken to ensure that this file exists only in the master branch. Here is the repository.yml file from the apache-Mynewt-core: repo.name: apache-mynewt-core repo.versions: \"0.0.0\": \"master\" \"0.0.1\": \"master\" \"0.7.9\": \"mynewt_0_8_0_b2_tag\" \"0.8.0\": \"mynewt_0_8_0_tag\" \"0.9.0\": \"mynewt_0_9_0_tag\" \"0.9.9\": \"mynewt_1_0_0_b1_tag\" \"0.9.99\": \"mynewt_1_0_0_b2_tag\" \"0.9.999\": \"mynewt_1_0_0_rc1_tag\" \"1.0.0\": \"mynewt_1_0_0_tag\" \"0-latest\": \"1.0.0\" # 1.0.0 \"0-dev\": \"0.0.0\" # master \"0.8-latest\": \"0.8.0\" \"0.9-latest\": \"0.9.0\" \"1.0-latest\": \"1.0.0\" # 1.0.0 It contains the following: repo.name The external name that is used to include the library in your project.yml file. This is the name you in include in the project.repositories variable when adding this repository to your project. repo.versions A description of what versions to give the user depending on the settings in their project.yml file.","title":"Identifying a Repo"},{"location":"os/tutorials/repo/add_repos/#repo-version","text":"The repo version number resolves to an actual git branch depending on the mapping specified in repository.yml for that repo. The version field argument in your project.yml file supports multiple formats for flexibility: <major_num>.<minor_num>.<revision_num> or <major_num>.<minor_num>-<stability string> or <major_num>-<stability string> The stability string can be one of 3 pre-defined stability values. stable -- A stable release version of the repository dev -- A development version from the repository latest -- The latest from the repository In your project.yml file you can specify different combinations of the version number and stability value. For example: 1-latest -- The latest version with major number 1 1.2-stable -- The latest stable version with major and minor number 1.2 1.2-dev -- The development version from 1.2 1.1.1 -- a specific version 1.1.1 You cannot specify a stability string with a fully numbered version, e.g. 1.2.8-stable","title":"Repo Version"},{"location":"os/tutorials/repo/add_repos/#repo-versions-available","text":"A repository.yml file contains information to match a version request into a git branch to fetch for your project. It's up to the repository maintainer to map these to branches of the repository. For example, let's say in a fictitious repository the following are defined. repo.versions: \"0.8.0\": \"xxx_branch_0_8_0\" \"1.0.0\": \"xxx_branch_1_0_0\" \"1.0.2\": \"xxx_branch_1_0_2\" \"1.1.1\": \"xxx_branch_1_1_0\" \"1.1.2\": \"xxx_branch_1_1_2\" \"1.2.0\": \"xxx_branch_1_2_0\" \"1.2.1\": \"xxx_branch_1_2_1\" \"1.2-dev\": \"1.2.1\" \"1-dev\": \"1.2-dev\" \"1.2-stable\": \"1.2.0\" \"0-latest\": \"0.8.0\" \"1-latest\": \"1-dev\" .... When the project.yml file asks for 1.2-stable it is resolved to version 1.2.0 (perhaps 1.2.1 is not stable yet), which in turn resolves to a specific branch xxx_branch_1_2_0 . This is the branch that newt fetches into your project. Note: Make sure a repo version exists in the repository.yml file of a repo you wish to add. Otherwise Newt will not be able to resolve the version and will fail to fetch the repo into your project.","title":"Repo Versions Available"},{"location":"os/tutorials/repo/add_repos/#how-to-find-out-what-repos-are-available-for-mynewt-components","text":"Currently, there is no newt command to locate/search Mynewt package repositories. However, since the newt tool supports only github, searching github by keyword is a satisfactory option until a search tool is created. When searching github, recall that a Mynewt repository must have a repository.yml file in its root directory. If you don't see that file, it's not a Mynewt repository and can't be included in your project via the newt tool. Once you find a repository, the github URL and repository.yml file should give you all the information to add it to your project.yml file.","title":"How to find out what Repos are available for Mynewt components"},{"location":"os/tutorials/repo/create_repo/","text":"Create a Repo out of a Project In order to create a repository out of a project, all you need to do is create a repository.yml file, and check it into the master branch of your project. NOTE: Currently only github source control service is supported by our package management system, but support for plain git is planned for a future version. The repository.yml defines all versions of the repository and the corresponding source control tags that these versions correspond to. As an example, if the repository.yml file has the following content, it means there is one version of the apache-mynewt-core operating system available, which is 0.0.0 (implying we haven't released yet!). Such a version number corresponds to the \"develop\" branch in this repository. 0-latest would also resolved to this same 0.0.0 version. The next section explains the versioning system a bit more. $ more repository.yml repo.name: apache-mynewt-core repo.versions: \"0.0.0\": \"develop\" \"0-latest\": \"0.0.0\" Where should the repository.yml file be? The repository.yml file lives only in the master branch of the git repository. Newt will always fetch this file from the master branch and then use that to resolve the actual branch required depending on the version specified in the project. Special care should be taken to ensure that this file exists only in the master branch. Here is the repository.yml file from a certain snapshot of apache-Mynewt-core: repo.name: apache-mynewt-core repo.versions: \"0.7.9\": \"Mynewt_0_8_0_b2_tag\" \"0-latest\": \"0.7.9\" \"0.8-latest\": \"0.7.9\" It contains the following: repo.name The external name that is used to include the library in your project.yml file. This is the name you include in the project.repositories variable when adding this repository to your project. repo.versions A description of what versions to give the user depending on the settings in their project.yml file. See below for a thorough description on versioning. Its a flexible mapping between version numbers and git branches. Repo Version Specification The version field argument for a repo has the following format: <major_num>.<minor_num>.<revision_num> or <major_num>.<minor_num>-<stability string> or <major_num>-<stability string> The stability string can be one of 3 pre-defined stability values. stable -- A stable release version of the repository dev -- A development version from the repository latest -- The latest from the repository In your project.yml file you can specify different combinations of the version number and stability value. For example: 1-latest -- The latest version with major number 1 1.2-stable -- The latest stable version with major and minor number 1.2 1.2-dev -- The development version from 1.2 1.1.1 -- a specific version 1.1.1 You cannot specify a stability string with a fully numbered version, e.g. 1.2.8-stable Repo Version Resolution A repository.yml file contains information to match this version request into a git branch to fetch for your project. It's up to you as the repository maintainer to map these to actual github branches of the repository. For example, let's say in a fictitious repository the following are defined. repo.versions: \"0.8.0\": \"xxx_branch_0_8_0\" \"1.0.0\": \"xxx_branch_1_0_0\" \"1.0.2\": \"xxx_branch_1_0_2\" \"1.1.1\": \"xxx_branch_1_1_0\" \"1.1.2\": \"xxx_branch_1_1_2\" \"1.2.0\": \"xxx_branch_1_2_0\" \"1.2.1\": \"xxx_branch_1_2_1\" \"1.2-dev\": \"1.2.1\" \"1-dev\": \"1.2-dev\" \"1.2-stable\": \"1.2.0\" \"0-latest\": \"0.8.0\" \"1-latest\": \"1-dev\" .... When the project.yml file asks for 1.2-stable it will be resolved to version 1.2.0 which in turn will resolve to a specific branch xxx_branch_1_2_0 . This is the branch that newt will then fetch into the project with that project.yml file. Dependencies on other repos Repositories can also have dependencies on other repositories. These dependencies should be listed out on a per-tag basis. So, for example, if apache-mynewt-core were to depend on sterlys-little-repo, you might have the following directives in the repository.yml: develop.repositories: sterlys-little-repo: type: github vers: 0.8-latest user: sterlinghughes repo: sterlys-little-repo This would tell Newt that for anything that resolves to the develop branch, this repository requires the sterlys-little-repo repository. Dependencies are resolved circularly by the newt tool, and every dependent repository is placed as a sibling in the repos directory. Currently, if two repositories have the same name, they will conflict and bad things will happen. When a repository is installed to the repos/ directory, the current version of that repository is written to the project.state file. The project state file contains the currently installed version of any given repository. This way, the current set of repositories can be recreated from the project.state file reliably, whereas the project.yml file can have higher level directives (i.e. include 0.8-stable.) Resolving dependencies At the moment, all dependencies must match, otherwise newt will provide an error. As an example, if you have a set of dependencies such that: apache-mynewt-core depends on sterlys-little-repo 0.6-stable apache-mynewt-core depends on sterlys-big-repo 0.5.1 sterlys-big-repo-0.5.1 depends on sterlys-little-repo 0.6.2 where 0.6-stable is 0.6.3, the newt tool will try and resolve the dependency to sterlys-little-repo. It will notice that there are two conflicting versions of the same repository, and not perform installation. In the future Newt will be smarter about loading in all dependencies, and then looking to satisfy those dependencies to the best match of all potential options.","title":"Turn project into a Repo"},{"location":"os/tutorials/repo/create_repo/#create-a-repo-out-of-a-project","text":"In order to create a repository out of a project, all you need to do is create a repository.yml file, and check it into the master branch of your project. NOTE: Currently only github source control service is supported by our package management system, but support for plain git is planned for a future version. The repository.yml defines all versions of the repository and the corresponding source control tags that these versions correspond to. As an example, if the repository.yml file has the following content, it means there is one version of the apache-mynewt-core operating system available, which is 0.0.0 (implying we haven't released yet!). Such a version number corresponds to the \"develop\" branch in this repository. 0-latest would also resolved to this same 0.0.0 version. The next section explains the versioning system a bit more. $ more repository.yml repo.name: apache-mynewt-core repo.versions: \"0.0.0\": \"develop\" \"0-latest\": \"0.0.0\"","title":"Create a Repo out of a Project"},{"location":"os/tutorials/repo/create_repo/#where-should-the-repositoryyml-file-be","text":"The repository.yml file lives only in the master branch of the git repository. Newt will always fetch this file from the master branch and then use that to resolve the actual branch required depending on the version specified in the project. Special care should be taken to ensure that this file exists only in the master branch. Here is the repository.yml file from a certain snapshot of apache-Mynewt-core: repo.name: apache-mynewt-core repo.versions: \"0.7.9\": \"Mynewt_0_8_0_b2_tag\" \"0-latest\": \"0.7.9\" \"0.8-latest\": \"0.7.9\" It contains the following: repo.name The external name that is used to include the library in your project.yml file. This is the name you include in the project.repositories variable when adding this repository to your project. repo.versions A description of what versions to give the user depending on the settings in their project.yml file. See below for a thorough description on versioning. Its a flexible mapping between version numbers and git branches.","title":"Where should the repository.yml file be?"},{"location":"os/tutorials/repo/create_repo/#repo-version-specification","text":"The version field argument for a repo has the following format: <major_num>.<minor_num>.<revision_num> or <major_num>.<minor_num>-<stability string> or <major_num>-<stability string> The stability string can be one of 3 pre-defined stability values. stable -- A stable release version of the repository dev -- A development version from the repository latest -- The latest from the repository In your project.yml file you can specify different combinations of the version number and stability value. For example: 1-latest -- The latest version with major number 1 1.2-stable -- The latest stable version with major and minor number 1.2 1.2-dev -- The development version from 1.2 1.1.1 -- a specific version 1.1.1 You cannot specify a stability string with a fully numbered version, e.g. 1.2.8-stable","title":"Repo Version Specification"},{"location":"os/tutorials/repo/create_repo/#repo-version-resolution","text":"A repository.yml file contains information to match this version request into a git branch to fetch for your project. It's up to you as the repository maintainer to map these to actual github branches of the repository. For example, let's say in a fictitious repository the following are defined. repo.versions: \"0.8.0\": \"xxx_branch_0_8_0\" \"1.0.0\": \"xxx_branch_1_0_0\" \"1.0.2\": \"xxx_branch_1_0_2\" \"1.1.1\": \"xxx_branch_1_1_0\" \"1.1.2\": \"xxx_branch_1_1_2\" \"1.2.0\": \"xxx_branch_1_2_0\" \"1.2.1\": \"xxx_branch_1_2_1\" \"1.2-dev\": \"1.2.1\" \"1-dev\": \"1.2-dev\" \"1.2-stable\": \"1.2.0\" \"0-latest\": \"0.8.0\" \"1-latest\": \"1-dev\" .... When the project.yml file asks for 1.2-stable it will be resolved to version 1.2.0 which in turn will resolve to a specific branch xxx_branch_1_2_0 . This is the branch that newt will then fetch into the project with that project.yml file.","title":"Repo Version Resolution"},{"location":"os/tutorials/repo/create_repo/#dependencies-on-other-repos","text":"Repositories can also have dependencies on other repositories. These dependencies should be listed out on a per-tag basis. So, for example, if apache-mynewt-core were to depend on sterlys-little-repo, you might have the following directives in the repository.yml: develop.repositories: sterlys-little-repo: type: github vers: 0.8-latest user: sterlinghughes repo: sterlys-little-repo This would tell Newt that for anything that resolves to the develop branch, this repository requires the sterlys-little-repo repository. Dependencies are resolved circularly by the newt tool, and every dependent repository is placed as a sibling in the repos directory. Currently, if two repositories have the same name, they will conflict and bad things will happen. When a repository is installed to the repos/ directory, the current version of that repository is written to the project.state file. The project state file contains the currently installed version of any given repository. This way, the current set of repositories can be recreated from the project.state file reliably, whereas the project.yml file can have higher level directives (i.e. include 0.8-stable.)","title":"Dependencies on other repos"},{"location":"os/tutorials/repo/create_repo/#resolving-dependencies","text":"At the moment, all dependencies must match, otherwise newt will provide an error. As an example, if you have a set of dependencies such that: apache-mynewt-core depends on sterlys-little-repo 0.6-stable apache-mynewt-core depends on sterlys-big-repo 0.5.1 sterlys-big-repo-0.5.1 depends on sterlys-little-repo 0.6.2 where 0.6-stable is 0.6.3, the newt tool will try and resolve the dependency to sterlys-little-repo. It will notice that there are two conflicting versions of the same repository, and not perform installation. In the future Newt will be smarter about loading in all dependencies, and then looking to satisfy those dependencies to the best match of all potential options.","title":"Resolving dependencies"},{"location":"os/tutorials/repo/private_repo/","text":"Accessing a private repository To access a private repository, newt needs to be configured with one of the following: Access token for the repository Basic auth login and password for the user NOTE: To create a github access token, see https://help.github.com/articles/creating-an-access-token-for-command-line-use/ There are two ways to specify this information, as shown below. In these examples, both a token and a login/password are specified, but you only need to specify one of these. 1. project.yml (probably world-readable and therefore not secure): repository.my-private-repo: type: github vers: 0-dev user: owner-of-repo repo: repo-name token: '8ab6433f8971b05c2a9c3341533e8ddb754e404e' login: githublogin password: githubpassword 2. $HOME/.newt/repos.yml repository.my-private-repo: token: '8ab6433f8971b05c2a9c3341533e8ddb754e404e' login: githublogin password: githubpassword If both a token and a login+password are specified, newt uses the token. If both the project.yml file and the private repos.yml file specify security credentials, newt uses the project.yml settings. NOTE: When newt downloads the actual repo content, as opposed to just the repository.yml file, it does not use the same mechanism. Instead, it invokes the git command line tool. This is an annoyance because the user cannot use the same access token for all git operations. This is something that will be fixed in the future.","title":"Access a private Repo"},{"location":"os/tutorials/repo/private_repo/#accessing-a-private-repository","text":"To access a private repository, newt needs to be configured with one of the following: Access token for the repository Basic auth login and password for the user NOTE: To create a github access token, see https://help.github.com/articles/creating-an-access-token-for-command-line-use/ There are two ways to specify this information, as shown below. In these examples, both a token and a login/password are specified, but you only need to specify one of these. 1. project.yml (probably world-readable and therefore not secure): repository.my-private-repo: type: github vers: 0-dev user: owner-of-repo repo: repo-name token: '8ab6433f8971b05c2a9c3341533e8ddb754e404e' login: githublogin password: githubpassword 2. $HOME/.newt/repos.yml repository.my-private-repo: token: '8ab6433f8971b05c2a9c3341533e8ddb754e404e' login: githublogin password: githubpassword If both a token and a login+password are specified, newt uses the token. If both the project.yml file and the private repos.yml file specify security credentials, newt uses the project.yml settings. NOTE: When newt downloads the actual repo content, as opposed to just the repository.yml file, it does not use the same mechanism. Instead, it invokes the git command line tool. This is an annoyance because the user cannot use the same access token for all git operations. This is something that will be fixed in the future.","title":"Accessing a private repository"},{"location":"os/tutorials/repo/upgrade_repo/","text":"Upgrade a repo In order to upgrade a previously installed repository, the \"newt upgrade\" command should be issued: $ newt upgrade Newt upgrade will look at the current desired version in project.yml , and compare it to the version in project.state . If these two differ, it will upgrade the dependency. Upgrade works not just for the dependency in project.yml , but for all the sub-dependencies that they might have. If you have changed any settings in the project.yml file, you should run newt upgrade to ensure that your repos are all up to date with the versions specified in your project.yml file.","title":"Upgrade a Repo"},{"location":"os/tutorials/repo/upgrade_repo/#upgrade-a-repo","text":"In order to upgrade a previously installed repository, the \"newt upgrade\" command should be issued: $ newt upgrade Newt upgrade will look at the current desired version in project.yml , and compare it to the version in project.state . If these two differ, it will upgrade the dependency. Upgrade works not just for the dependency in project.yml , but for all the sub-dependencies that they might have. If you have changed any settings in the project.yml file, you should run newt upgrade to ensure that your repos are all up to date with the versions specified in your project.yml file.","title":"Upgrade a repo"},{"location":"pages/ble/","text":"","title":"Bluetooth Low Energy 4.2"},{"location":"pages/configurability/","text":"","title":"Configurability"}]}