You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mynewt.apache.org by ad...@apache.org on 2016/06/27 22:16:28 UTC

[2/9] incubator-mynewt-site git commit: Added changes from pull request #96 by davidgs

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-site/blob/4c442db2/v0_9_0/mkdocs/search_index.json
----------------------------------------------------------------------
diff --git a/v0_9_0/mkdocs/search_index.json b/v0_9_0/mkdocs/search_index.json
index 5d2c26d..a8b412c 100644
--- a/v0_9_0/mkdocs/search_index.json
+++ b/v0_9_0/mkdocs/search_index.json
@@ -987,7 +987,7 @@
         }, 
         {
             "location": "/os/tutorials/air_quality_sensor/", 
-            "text": "Air quality sensor project\n\n\nSetting up source tree for stuff you need\n\n\nTo start with, you need to create a new project under which you will do this development. So you type in:\n\n\n    $ mkdir $HOME/src\n    $ cd $HOME/src\n    $ newt new air_quality\n\n\n\n\n\nLet's say you are using STM32F3discovery board 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.\n\n\nTo make this happen, you'll need to modify the project.yml in your project's root directory.\n\n\n    [user@IsMyLaptop:~/src/air_quality]$ emacs project.yml \n\n    [user@IsMyLaptop:~/src/air_quality]$ cat project.yml\n    project.name: \nair_quality\n\n\n    project.repositories:\n        - apache-mynewt-core\n        - mynewt_stm32f3\n\n    # Use github\ns distribution mechanism for core ASF libraries.\n    # This provides mirroring automatically for us.\n    #\n   
  repository.apache-mynewt-core:\n        type: github\n        vers: 0-latest\n        user: apache\n        repo: incubator-mynewt-core\n\n    repository.mynewt_stm32f3:\n        type: github\n        vers: 0-latest\n        user: runtimeinc\n        repo: mynewt_stm32f3\n    [user@IsMyLaptop:~/src/air_quality]$ newt install\n    apache-mynewt-core\n    mynewt_stm32f3\n    [user@IsMyLaptop:~/src/air_quality]$ ls repos/\n    apache-mynewt-core  mynewt_stm32f3\n\n\n\n\n\nGood. 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.\n\n\nNow 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 STM32F3Discovery board.\n\n\n[user@IsMyLaptop:~/src/air_quality]$ newt target copy my_blinky_sim blink_f3\nTarget successfully copied; targets/my_blinky_sim --\n targets/blink_f3\n[user@IsMyLaptop:~/src/air_quality]$ newt target set 
 blink_f3 bsp=@mynewt_stm32f3/hw/bsp/stm32f3discovery\nTarget targets/blink_f3 successfully set target.bsp to @mynewt_stm32f3/hw/bsp/stm32f3discovery\n[user@IsMyLaptop:~/src/air_quality]$ newt build blink_f3\nCompiling hal_bsp.c\n...\nLinking blinky.elf\nApp successfully built: /Users/user/src/air_quality/bin/blink_f3/apps/blinky/blinky.elf\n\n\n\n\n\nGood.\n\n\nYou know that this platform uses bootloader, which means you have to create a target for that too.\n\n\n[user@IsMyLaptop:~/src/air_quality]$ newt target create boot_f3\nTarget targets/boot_f3 successfully created\n[user@IsMyLaptop:~/src/air_quality]$ newt target show\n@apache-mynewt-core/targets/unittest\n    bsp=hw/bsp/native\n    build_profile=debug\n    compiler=compiler/sim\ntargets/blink_f3\n    app=apps/blinky\n    bsp=@mynewt_stm32f3/hw/bsp/stm32f3discovery\n    build_profile=debug\ntargets/boot_f3\ntargets/my_blinky_sim\n    app=apps/blinky\n    bsp=@apache-mynewt-core/hw/bsp/native\n    build_profile=debug\n[user@IsM
 yLaptop:~/src/air_quality]$ newt target set boot_f3 bsp=@mynewt_stm32f3/hw/bsp/stm32f3discovery\nTarget targets/boot_f3 successfully set target.bsp to @mynewt_stm32f3/hw/bsp/stm32f3discovery\n[user@IsMyLaptop:~/src/air_quality]$ newt target set boot_f3 app=@apache-mynewt-core/apps/boot\nTarget targets/boot_f3 successfully set target.app to @apache-mynewt-core/apps/boot\n[user@IsMyLaptop:~/src/air_quality]$ newt target set boot_f3 build_profile=optimized\nTarget targets/boot_f3 successfully set target.build_profile to optimized\n\n\n\n\n\nAnd then build it, and load it onto the board.\n\n\nnewt build boot_f3\n....\nLinking boot.elf\nApp successfully built: /Users/user/src/air_quality/bin/boot_f3/apps/boot/boot.elf\n[user@IsMyLaptop:~/src/air_quality]$ newt load boot_f3\n\n\n\n\n\nNext you must download the targets to board, and see that the LED actually blinks. You plug in the STM32F3 discovery board to your laptop, and say:\n\n\n[user@IsMyLaptop:~/src/air_quality]$ newt load blink_f
 3\nDownloading /Users/user/src/air_quality/bin/blink_f3/apps/blinky/blinky.img to 0x08009000\nOpen On-Chip Debugger 0.9.0 (2015-05-28-12:05)\n....\nxPSR: 0x01000000 pc: 0x0800026c msp: 0x10002000\nauto erase enabled\nError: couldn\nt open /Users/user/src/air_quality/bin/blink_f3/apps/blinky/blinky.img\n\nError: exit status 1\n\nload - Load app image to target for \ntarget-name\n.\n\nUsage:\n  newt load [flags]\n\nExamples:\n  newt load \ntarget-name\n\n\n\nGlobal Flags:\n  -l, --loglevel string   Log level, defaults to WARN. (default \nWARN\n)\n  -o, --outfile string    Filename to tee log output to\n  -q, --quiet             Be quiet; only display error output.\n  -s, --silent            Be silent; don\nt output anything.\n  -v, --verbose           Enable verbose output when executing commands.\nexit status 1\n\n\n\n\n\nAh. 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 target board, you need to run 'creat
 e-image' on it.\n\n\n[user@IsMyLaptop:~/src/air_quality]$ newt create-image blink_f3 0.0.1\nApp image successfully generated: /Users/user/src/air_quality/bin/blink_f3/apps/blinky/blinky.img\nBuild manifest: /Users/user/src/air_quality/bin/blink_f3/apps/blinky/manifest.json\n[user@IsMyLaptop:~/src/air_quality]$ newt load blink_f3 0.0.1\n\n\n\n\n\nAnd it's blinking.\n\n\nShortcut for doing build/create-image/load/debug steps all in one is 'newt run' command. Check out the usage from command line help.\n\n\nCreate test project\n\n\nNow that you have your system setup, you can start creating your own stuff.\nFirst you want to create a project for yourself - you can start by getting project template from blinky, as it pretty much has what you want.\n\n\n    [user@IsMyLaptop:~/src/air_quality]$ mkdir apps/air_quality\n    [user@IsMyLaptop:~/src/air_quality]$ cp repos/apache-mynewt-core/apps/blinky/pkg.yml apps/air_quality/\n    [user@IsMyLaptop:~/src/air_quality]$ mkdir apps/air_quality/s
 rc\n    [user@IsMyLaptop:~/src/air_quality]$ cp repos/apache-mynewt-core/apps/blinky/src/main.c apps/air_quality/src/\n\n\n\n\n\nThen you modify the apps/air_quality/pkg.yml for air_quality in order to change the \npkg.name\n to be \napps/air_quality\n.\nYou also need to point the package dependencies to point to packages in apache-mynewt-core repository.\nSTM32F3discovery board has limited amount of memory, so you must also switch your libc to be baselibc, instead of the standard one.\n\n\n[user@IsMyLaptop:~/src/air_quality]$ cat apps/air_quality/pkg.yml\npkg.name: apps/air_quality\npkg.type: app\npkg.description: Air quality sensor test\npkg.keywords:\n\npkg.deps:\n    - \n@apache-mynewt-core/libs/console/full\n\n    - \n@apache-mynewt-core/libs/newtmgr\n\n    - \n@apache-mynewt-core/libs/os\n\n    - \n@apache-mynewt-core/libs/shell\n\n    - \n@apache-mynewt-core/sys/config\n\n    - \n@apache-mynewt-core/sys/log\n\n    - \n@apache-mynewt-core/sys/stats\n\n    - \n@apache-mynewt-co
 re/libs/baselibc\n\n\n\n\n\n\nAnd create a target for it:\n\n\n[user@IsMyLaptop:~/src/air_quality]$ newt target create air_q\nTarget targets/air_q successfully created\n[user@IsMyLaptop:~/src/air_quality]$ newt target set air_q bsp=@mynewt_stm32f3/hw/bsp/stm32f3discovery\nTarget targets/air_q successfully set target.bsp to @mynewt_stm32f3/hw/bsp/stm32f3discovery\n[user@IsMyLaptop:~/src/air_quality]$ newt target set air_q app=apps/air_quality \nTarget targets/air_q successfully set target.app to apps/air_quality\n[user@IsMyLaptop:~/src/air_quality]$ newt target set air_q build_profile=debug\nTarget targets/air_q successfully set target.build_profile to debug\n[user@IsMyLaptop:~/src/air_quality]$ newt build air_q\n ....\nLinking air_quality.elf\nApp successfully built: /Users/user/src/air_quality/bin/air_q/apps/air_quality/air_quality.elf\n\n\n\n\n\nCreate packages for drivers\n\n\nOne of the sensors you want to enable is SenseAir K30, which will connect to the board over serial port.
 \nTo start development of the driver, you first need to create a package description for it, and add stubs for sources.\n\n\nSo you add few files. pkg.yml to describe the driver, and then header stub followed by source stub.\n\n\n[user@IsMyLaptop:~/src/air_quality]$ cat libs/my_drivers/senseair/pkg.yml\n\n\n\n\n\n#\n\n\n# Licensed to the Apache Software Foundation (ASF) under one\n\n\n# or more contributor license agreements.  See the NOTICE file\n\n\n# distributed with this work for additional information\n\n\n# regarding copyright ownership.  The ASF licenses this file\n\n\n# to you under the Apache License, Version 2.0 (the\n\n\n# \nLicense\n); you may not use this file except in compliance\n\n\n# with the License.  You may obtain a copy of the License at\n\n\n# \n\n\n#  http:\n//www.apache.org/licenses/LICENSE-2.0\n\n\n#\n\n\n# Unless required by applicable law or agreed to in writing,\n\n\n# software distributed under the License is distributed on an\n\n\n# \nAS IS\n BASIS, WIT
 HOUT WARRANTIES OR CONDITIONS OF ANY\n\n\n# KIND, either express or implied.  See the License for the\n\n\n# specific language governing permissions and limitations\n\n\n# under the License.\n\n\n#\n\n\npkg\n.\nname\n: \nlibs/my_drivers/senseair\n\n\npkg\n.\ndeps\n:\n    \n-\n \n@apache-mynewt-core/hw/hal\n\n\n\n\n\n\n[user@IsMyLaptop:~/src/air_quality]$ cat libs/my_drivers/senseair/include/senseair/senseair.h\n\n\n\n\n\n/*\n\n\n * Licensed to the Apache Software Foundation (ASF) under one\n\n\n * or more contributor license agreements.  See the NOTICE file\n\n\n * distributed with this work for additional information\n\n\n * regarding copyright ownership.  The ASF licenses this file\n\n\n * to you under the Apache License, Version 2.0 (the\n\n\n * \nLicense\n); you may not use this file except in compliance\n\n\n * with the License.  You may obtain a copy of the License at\n\n\n * \n\n\n *  http://www.apache.org/licenses/LICENSE-2.0\n\n\n *\n\n\n * Unless required by applicable law
  or agreed to in writing,\n\n\n * software distributed under the License is distributed on an\n\n\n * \nAS IS\n BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n\n\n * KIND, either express or implied.  See the License for the\n\n\n * specific language governing permissions and limitations\n\n\n * under the License.\n\n\n*/\n\n\n#ifndef _SENSEAIR_H_\n\n\n#define _SENSEAIR_H_\n\n\n\nvoid\n \nsenseair_init\n(\nvoid\n);\n\n\n#endif \n/* _SENSEAIR_H_ */\n\n\n\n\n\n\n[user@IsMyLaptop:~/src/air_quality]$ cat libs/my_drivers/senseair/src/senseair.c\n\n\n\n\n\n/**\n\n\n * Licensed to the Apache Software Foundation (ASF) under one\n\n\n * or more contributor license agreements.  See the NOTICE file\n\n\n * distributed with this work for additional information\n\n\n * regarding copyright ownership.  The ASF licenses this file\n\n\n * to you under the Apache License, Version 2.0 (the\n\n\n * \nLicense\n); you may not use this file except in compliance\n\n\n * with the License.  You may obtain a 
 copy of the License at\n\n\n * \n\n\n *  http://www.apache.org/licenses/LICENSE-2.0\n\n\n *\n\n\n * Unless required by applicable law or agreed to in writing,\n\n\n * software distributed under the License is distributed on an\n\n\n * \nAS IS\n BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n\n\n * KIND, either express or implied.  See the License for the\n\n\n * specific language governing permissions and limitations\n\n\n * under the License.\n\n\n */\n\n\n\nvoid\n\n\nsenseair_init\n(\nvoid\n)\n{\n}\n\n\n\n\n\nAnd add dependency to this package in my project yml file.\n\n\nHere's from apps/air_quality/pkg.yml\n\n\npkg.name: apps/air_quality\npkg.type: app\npkg.description: Air quality sensor test\npkg.keywords:\n\npkg.deps:\n    - \n@apache-mynewt-core/libs/console/full\n\n    - \n@apache-mynewt-core/libs/newtmgr\n\n    - \n@apache-mynewt-core/libs/os\n\n    - \n@apache-mynewt-core/libs/shell\n\n    - \n@apache-mynewt-core/sys/config\n\n    - \n@apache-mynewt-core/sys/log\n\n    -
  \n@apache-mynewt-core/sys/stats\n\n    - \n@apache-mynewt-core/libs/baselibc\n\n    - libs/my_drivers/senseair\n\n\n\n\n\nAnd add a call to your main() to initialize this driver.\n\n\n    [user@IsMyLaptop:~/src/air_quality]$ diff project/blinky/src/main.c project/air_quality/src/main.c\n    28a29\n    \n #include \nsenseair/senseair.h\n\n    190a192\n    \n senseair_init();\n    [user@IsMyLaptop:~/src/air_quality\n\n\n\n\n\nAnd then build it to make sure all goes well.\n\n\n[user@IsMyLaptop:~/src/air_quality]$ newt build air_q\nCompiling senseair.c\nArchiving senseair.a\nLinking air_quality.elf\nApp successfully built: /Users/user/src/air_quality/bin/air_q/apps/air_quality/air_quality.elf\n\n\n\n\n\nAll looks good.\n\n\nAdd CLI commands for testing drivers\n\n\nWhile developing the driver, you want to issue operations from console asking it to do stuff. The way to do this is to register your command handler with shell. Whenever your custom command is issued, you can respond to it.\
 n\n\nThe way you do this is first adding a dependency to shell package for your senseair driver. So you change libs/my_drivers/senseair/pkg.yml to have the following:\n\n\npkg.name: libs/my_drivers/senseair\npkg.deps:\n    - \n@apache-mynewt-core/hw/hal\n\n    - \n@apache-mynewt-core/libs/shell\n\n\n\n\n\n\nAnd then register your shell command in \nsenseair_init()\n.\n\n\n[user@IsMyLaptop:~/src/air_quality]$ cat libs/my_drivers/senseair/src/senseair.c\n ....\n\n\n\n\n\n#include \nshell/shell.h\n\n\n#include \nconsole/console.h\n\n\n\nstatic\n \nint\n \nsenseair_shell_func\n(\nint\n \nargc\n, \nchar\n \n**argv\n);\n\nstatic\n \nstruct\n \nshell_cmd\n \nsenseair_cmd\n \n=\n {\n    .\nsc_cmd\n \n=\n \nsenseair\n,\n    .\nsc_cmd_func\n \n=\n \nsenseair_shell_func\n,\n};\n\n\nvoid\n\n\nsenseair_init\n(\nvoid\n)\n{\n    \nint\n \nrc\n;\n\n    \nrc\n \n=\n \nshell_cmd_register\n(\nsenseair_cmd\n);\n    \nassert\n(\nrc\n \n==\n \n0\n);\n}\n\n\nstatic\n \nint\n\n\nsenseair_shell_func\n(\nint
 \n \nargc\n, \nchar\n \n**argv\n)\n{\n    \nconsole_printf\n(\nYay! Somebody called!\\n\n);\n    \nreturn\n \n0\n;\n}\n\n\n\n\n\nThen you build this, download to target, and start minicom on your console port.\n\n\n    [user@IsMyLaptop:~]$ minicom -D /dev/tty.usbserial-AH02MIE2\n\n\n    Welcome to minicom 2.7\n\n    OPTIONS: \n    Compiled on Oct 12 2015, 07:48:30.\n    Port /dev/tty.usbserial-AH02MIE2, 13:44:40\n\n    Press CTRL-X Z for help on special keys\n\n    ?\n    141964:Unknown command ?\n    ?\n    143804:config   log     echo    ?       tasks   mempools \n    143806:stat     senseair \n    senseair\n    150644:Yay! Somebody called!\n\n\n\n\n\nNow that's great. You can connect the hardware to board and start developing code for the driver itself.\n\n\nUse of HAL for drivers\n\n\nThe sensor has a serial port connection, and that's how you are going to connect to it. Your original BSP, hw/bsp/stm32f3discovery, has only one UART set up (as specified in src/hal_bsp.c, include/
 hal/bsp.h). Therefore, you need to create your own bsp which has configuration for this added hardware.\n\n\nSo in the shell you make a copy of the original BSP, and then change the package file a little.\n\n\n[user@IsMyLaptop:~/src/air_quality]$ mkdir hw\n[user@IsMyLaptop:~/src/air_quality]$ mkdir hw/bsp\n\n[user@IsMyLaptop:~/src/air_quality]$ cp -R repos/mynewt_stm32f3/hw/bsp/stm32f3discovery hw/bsp/stm32f3discovery_with_senseair\n\n\n\n\n\nThen you modify the pkg.yml in the copied BSP to assign name for this package. And modify the dependency for MCU package to point to mynewt_stm32f3 repository.\n\n\n    [user@IsMyLaptop:~/src/air_quality]$ grep pkg.name hw/bsp/stm32f3discovery_with_senseair/pkg.yml\n    pkg.name: \nhw/bsp/stm32f3discovery_with_senseair\n\n    [user@IsMyLaptop:~/src/air_quality]$ tail -2 hw/bsp/stm32f3discovery_with_senseair/pkg.yml\npkg.deps:\n    - \n@mynewt_stm32f3/hw/mcu/stm/stm32f3xx\n\n\n\n\n\n\nAnd you want to use this BSP with my target. So you change th
 e BSP in the target definition.\n\n\nHere's your new target.\n\n\n[user@IsMyLaptop:~/src/air_quality]$ newt target show air_q\ntargets/air_q\n    app=apps/air_quality\n    bsp=hw/bsp/stm32f3discovery_with_senseair\n    build_profile=debug\n\n\n\n\n\nYou add the 2nd serial port to my new BSP. Go to hw/bsp/stm32f3discovery_with_senseair directory to do this.\n\n\nModify the include/hal/bsp.h to increase UART_CNT to 2, and add a definition of the 2nd logical UART. You will use this in your sensor driver.\n\n\nstatic\n \nconst\n \nstruct\n \nstm32f3_uart_cfg\n \nuart_cfg\n[\nUART_CNT\n] \n=\n {\n    [\n0\n] \n=\n {\n        .\nsuc_uart\n \n=\n \nUSART1\n,\n        .\nsuc_rcc_cmd\n \n=\n \nRCC_APB2PeriphClockCmd\n,\n        .\nsuc_rcc_dev\n \n=\n \nRCC_APB2Periph_USART1\n,\n        .\nsuc_pin_tx\n \n=\n \n9\n,\n        .\nsuc_pin_rx\n \n=\n \n10\n,\n        .\nsuc_pin_rts\n \n=\n \n12\n,\n        .\nsuc_pin_cts\n \n=\n \n11\n,\n        .\nsuc_pin_af\n \n=\n \nGPIO_AF_7\n,\n        .\nsuc
 _irqn\n \n=\n \nUSART1_IRQn\n\n    },\n    [\n1\n] \n=\n {\n        .\nsuc_uart\n \n=\n \nUSART2\n,\n        .\nsuc_rcc_cmd\n \n=\n \nRCC_APB1PeriphClockCmd\n,\n        .\nsuc_rcc_dev\n \n=\n \nRCC_APB1Periph_USART2\n,\n        .\nsuc_pin_tx\n \n=\n \n19\n, \n/* PB3 */\n\n        .\nsuc_pin_rx\n \n=\n \n20\n, \n/* PB4 */\n\n        .\nsuc_pin_rts\n \n=\n \n1\n,\n        .\nsuc_pin_cts\n \n=\n \n0\n,\n        .\nsuc_pin_af\n \n=\n \nGPIO_AF_7\n,\n        .\nsuc_irqn\n \n=\n \nUSART2_IRQn\n\n    }\n};\n\n\n\n\n\nWith this in place, you can refer to serial port where your SenseAir sensor is 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.\n\n\nYou will now see what the driver code ends up looking like. Here's the header file, filled
  in from stub you created earlier.\n\n\n/*\n\n\n * Licensed to the Apache Software Foundation (ASF) under one\n\n\n * or more contributor license agreements.  See the NOTICE file\n\n\n * distributed with this work for additional information\n\n\n * regarding copyright ownership.  The ASF licenses this file\n\n\n * to you under the Apache License, Version 2.0 (the\n\n\n * \nLicense\n); you may not use this file except in compliance\n\n\n * with the License.  You may obtain a copy of the License at\n\n\n * \n\n\n *  http://www.apache.org/licenses/LICENSE-2.0\n\n\n *\n\n\n * Unless required by applicable law or agreed to in writing,\n\n\n * software distributed under the License is distributed on an\n\n\n * \nAS IS\n BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n\n\n * KIND, either express or implied.  See the License for the\n\n\n * specific language governing permissions and limitations\n\n\n * under the License.\n\n\n*/\n\n\n#ifndef _SENSEAIR_H_\n\n\n#define _SENSEAIR_H_\n\n\n\nen
 um\n \nsenseair_read_type\n {\n        \nSENSEAIR_CO2\n,\n        \nSENSEAIR_TEMPERATURE\n,\n        \nSENSEAIR_HUMIDITY\n\n};\n\n\nint\n \nsenseair_init\n(\nint\n \nuartno\n);\n\n\nint\n \nsenseair_read\n(\nenum\n \nsenseair_read_type\n);\n\n\n#endif \n/* _SENSEAIR_H_ */\n\n\n\n\n\n\nAs 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.\n\n\nAnd here is the source for the driver.\n\n\n/**\n\n\n * Licensed to the Apache Software Foundation (ASF) under one\n\n\n * or more contributor license agreements.  See the NOTICE file\n\n\n * distributed with this work for additional information\n\n\n * regarding copyright ownership.  The ASF licenses this file\n\n\n * to you under the Apache License, Version 2.0 (the\n\n\n * \nLicense\n); you may not use this file except in compliance\n\n\n * with the License.  You 
 may obtain a copy of the License at\n\n\n *\n\n\n *  http://www.apache.org/licenses/LICENSE-2.0\n\n\n *\n\n\n * Unless required by applicable law or agreed to in writing,\n\n\n * software distributed under the License is distributed on an\n\n\n * \nAS IS\n BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n\n\n * KIND, either express or implied.  See the License for the\n\n\n * specific language governing permissions and limitations\n\n\n * under the License.\n\n\n */\n\n\n#include \nstring.h\n\n\n\n#include \nshell/shell.h\n\n\n#include \nconsole/console.h\n\n\n#include \nos/os.h\n\n\n\n#include \nhal/hal_uart.h\n\n\n\n#include \nsenseair/senseair.h\n\n\n\nstatic\n \nconst\n \nuint8_t\n \ncmd_read_co2\n[] \n=\n {\n    \n0xFE\n, \n0\nX44\n, \n0\nX00\n, \n0\nX08\n, \n0\nX02\n, \n0\nX9F\n, \n0\nX25\n\n};\n\nstatic\n \nconst\n \nuint8_t\n \ncmd_read_temp\n[] \n=\n {\n    \n0xFE\n, \n0\nX44\n, \n0\nX00\n, \n0\nX12\n, \n0\nX02\n, \n0\nX94\n, \n0\nX45\n\n};\n\nstatic\n \nconst\n \nuint8_t\n 
 \ncmd_read_humidity\n[] \n=\n {\n    \n0xFE\n, \n0x44\n, \n0x00\n, \n0x14\n, \n0x02\n, \n0x97\n, \n0xE5\n\n};\n\n\nstatic\n \nint\n \nsenseair_shell_func\n(\nint\n \nargc\n, \nchar\n \n**argv\n);\n\nstatic\n \nstruct\n \nshell_cmd\n \nsenseair_cmd\n \n=\n {\n    .\nsc_cmd\n \n=\n \nsenseair\n,\n    .\nsc_cmd_func\n \n=\n \nsenseair_shell_func\n,\n};\n\n\nstruct\n \nsenseair\n { \n    \nint\n \nuart\n;\n    \nstruct\n \nos_sem\n \nsema\n;\n    \nconst\n \nuint8_t\n \n*tx_data\n;\n    \nint\n \ntx_off\n;\n    \nint\n \ntx_len\n;\n    \nuint8_t\n \nrx_data\n[\n32\n]; \n    \nint\n \nrx_off\n;\n    \nint\n \nvalue\n;\n} \nsenseair\n;\n\n\nstatic\n \nint\n\n\nsenseair_tx_char\n(\nvoid\n \n*arg\n)\n{\n    \nstruct\n \nsenseair\n \n*s\n \n=\n \nsenseair\n;\n    \nint\n \nrc\n;\n\n    \nif\n (\ns-\ntx_off\n \n=\n \ns-\ntx_len\n) {\n    \n/*\n\n\n         * Command tx finished.\n\n\n         */\n\n        \ns-\ntx_data\n \n=\n \nNULL\n;\n        \nreturn\n \n-\n1\n;\n    }\n\n    \nrc\n \n=\
 n \ns-\ntx_data\n[\ns-\ntx_off\n];\n    \ns-\ntx_off++\n;\n    \nreturn\n \nrc\n;\n}\n\n\n/*\n\n\n * CRC for modbus over serial port.\n\n\n */\n\n\nstatic\n \nconst\n \nuint16_t\n \nmb_crc_tbl\n[] \n=\n {\n    \n0x0000\n, \n0xcc01\n, \n0xd801\n, \n0x1400\n, \n0xf001\n, \n0x3c00\n, \n0x2800\n, \n0xe401\n,\n    \n0xa001\n, \n0x6c00\n, \n0x7800\n, \n0xb401\n, \n0x5000\n, \n0x9c01\n, \n0x8801\n, \n0x4400\n\n};\n\n\nstatic\n \nuint16_t\n\n\nmb_crc\n(\nconst\n \nuint8_t\n \n*data\n, \nint\n \nlen\n, \nuint16_t\n \ncrc\n)\n{\n    \nwhile\n (\nlen--\n \n \n0\n) {\n        \ncrc\n \n^=\n \n*data++\n;\n        \ncrc\n \n=\n (\ncrc\n \n \n4\n) \n^\n \nmb_crc_tbl\n[\ncrc\n \n \n0xf\n];\n        \ncrc\n \n=\n (\ncrc\n \n \n4\n) \n^\n \nmb_crc_tbl\n[\ncrc\n \n \n0xf\n];\n    }\n    \nreturn\n \ncrc\n;\n}\n\n\nstatic\n \nint\n\n\nmb_crc_check\n(\nconst\n \nvoid\n \n*pkt\n, \nint\n \nlen\n)\n{\n    \nuint16_t\n \ncrc\n, \ncmp\n;\n    \nuint8_t\n \n*bp\n \n=\n (\nuint8_t\n \n*\n)\npkt\n;\n\n    \nif
 \n (\nlen\n \n \nsizeof\n(\ncrc\n) \n+\n \n1\n) {\n        \nreturn\n \n-\n1\n;\n    }\n    \ncrc\n \n=\n \nmb_crc\n(\npkt\n, \nlen\n \n-\n \n2\n, \n0xffff\n);\n    \ncmp\n \n=\n \nbp\n[\nlen\n \n-\n \n2\n] \n|\n (\nbp\n[\nlen\n \n-\n \n1\n] \n \n8\n);\n    \nif\n (\ncrc\n \n!=\n \ncmp\n) {\n        \nreturn\n \n-\n1\n;\n    } \nelse\n {\n        \nreturn\n \n0\n;\n    }\n}\n\n\nstatic\n \nint\n\n\nsenseair_rx_char\n(\nvoid\n \n*arg\n, \nuint8_t\n \ndata\n)\n{\n    \nstruct\n \nsenseair\n \n*s\n \n=\n (\nstruct\n \nsenseair\n \n*\n)\narg\n;\n    \nint\n \nrc\n;\n\n    \nif\n (\ns-\nrx_off\n \n=\n \nsizeof\n(\ns-\nrx_data\n)) {\n        \ns-\nrx_off\n \n=\n \n0\n;\n    }\n    \ns-\nrx_data\n[\ns-\nrx_off\n] \n=\n \ndata\n;\n    \ns-\nrx_off++\n;\n\n    \nif\n (\ns-\nrx_off\n \n==\n \n7\n) {\n        \nrc\n \n=\n \nmb_crc_check\n(\ns-\nrx_data\n, \ns-\nrx_off\n);\n        \nif\n (\nrc\n \n==\n \n0\n) {\n            \ns-\nvalue\n \n=\n \ns-\nrx_data\n[\n3\n] \n*\n \n256\n \n+\n \ns-\nr
 x_data\n[\n4\n];\n            \nos_sem_release\n(\ns-\nsema\n);\n        }\n    }\n    \nreturn\n \n0\n;\n}\n\n\nvoid\n\n\nsenseair_tx\n(\nstruct\n \nsenseair\n \n*s\n, \nconst\n \nuint8_t\n \n*tx_data\n, \nint\n \ndata_len\n)\n{\n    \ns-\ntx_data\n \n=\n \ntx_data\n;\n    \ns-\ntx_len\n \n=\n \ndata_len\n;\n    \ns-\ntx_off\n \n=\n \n0\n;\n    \ns-\nrx_off\n \n=\n \n0\n;\n\n    \nhal_uart_start_tx\n(\ns-\nuart\n);\n}\n\n\nint\n\n\nsenseair_read\n(\nenum\n \nsenseair_read_type\n \ntype\n)\n{\n    \nstruct\n \nsenseair\n \n*s\n \n=\n \nsenseair\n;\n    \nconst\n \nuint8_t\n \n*cmd\n;\n    \nint\n \ncmd_len\n;\n    \nint\n \nrc\n;\n\n    \nif\n (\ns-\ntx_data\n) {\n        \n/*\n\n\n         * busy\n\n\n         */\n\n        \nreturn\n \n-\n1\n;\n    }\n    \nswitch\n (\ntype\n) {\n    \ncase\n \nSENSEAIR_CO2\n:\n        \ncmd\n \n=\n \ncmd_read_co2\n;\n        \ncmd_len\n \n=\n \nsizeof\n(\ncmd_read_co2\n);\n        \nbreak\n;\n    \ncase\n \nSENSEAIR_TEMPERATURE\n:\n        \ncmd\
 n \n=\n \ncmd_read_temp\n;\n        \ncmd_len\n \n=\n \nsizeof\n(\ncmd_read_temp\n);\n        \nbreak\n;\n    \ncase\n \nSENSEAIR_HUMIDITY\n:\n        \ncmd\n \n=\n \ncmd_read_humidity\n;\n        \ncmd_len\n \n=\n \nsizeof\n(\ncmd_read_humidity\n);\n        \nbreak\n;\n    \ndefault\n:\n\n        \nreturn\n \n-\n1\n;\n    }\n    \nsenseair_tx\n(\ns\n, \ncmd\n, \ncmd_len\n);\n    \nrc\n \n=\n \nos_sem_pend\n(\ns-\nsema\n, \nOS_TICKS_PER_SEC\n \n/\n \n2\n);\n    \nif\n (\nrc\n \n==\n \nOS_TIMEOUT\n) {\n        \n/*\n\n\n         * timeout\n\n\n         */\n\n        \nreturn\n \n-\n2\n;\n    }\n    \nreturn\n \ns-\nvalue\n;\n}\n\n\nstatic\n \nint\n\n\nsenseair_shell_func\n(\nint\n \nargc\n, \nchar\n \n**argv\n)\n{\n    \nint\n \nvalue\n;\n    \nenum\n \nsenseair_read_type\n \ntype\n;\n\n    \nif\n (\nargc\n \n \n2\n) {\n\nusage\n:\n        \nconsole_printf\n(\n%s \nco2|temp|humidity\n\\n\n, \nargv\n[\n0\n]);\n        \nreturn\n \n0\n;\n    }\n    \nif\n (\n!strcmp\n(\nargv\n[\n1\n], 
 \nco2\n)) {\n        \ntype\n \n=\n \nSENSEAIR_CO2\n;\n    } \nelse\n \nif\n (\n!strcmp\n(\nargv\n[\n1\n], \ntemp\n)) {\n        \ntype\n \n=\n \nSENSEAIR_TEMPERATURE\n;\n    } \nelse\n \nif\n (\n!strcmp\n(\nargv\n[\n1\n], \nhumidity\n)) {\n        \n/*\n\n\n         * timeout\n\n\n         */\n\n        \nreturn\n \n-\n2\n;\n    }\n    \nreturn\n \ns-\nvalue\n;\n}\n\n\nstatic\n \nint\n\n\nsenseair_shell_func\n(\nint\n \nargc\n, \nchar\n \n**argv\n)\n{\n    \nint\n \nvalue\n;\n    \nenum\n \nsenseair_read_type\n \ntype\n;\n\n    \nif\n (\nargc\n \n \n2\n) {\n\nusage\n:\n        \nconsole_printf\n(\n%s \nco2|temp|humidity\n\\n\n, \nargv\n[\n0\n]);\n        \nreturn\n \n0\n;\n    }\n    \nif\n (\n!strcmp\n(\nargv\n[\n1\n], \nco2\n)) {\n        \ntype\n \n=\n \nSENSEAIR_CO2\n;\n    } \nelse\n \nif\n (\n!strcmp\n(\nargv\n[\n1\n], \ntemp\n)) {\n        \ntype\n \n=\n \nSENSEAIR_TEMPERATURE\n;\n    } \nelse\n \nif\n (\n!strcmp\n(\nargv\n[\n1\n], \nhumidity\n)) {\n        \ntype\n \n=\n \n
 SENSEAIR_HUMIDITY\n;\n    } \nelse\n {\n        \ngoto\n \nusage\n;\n    }\n    \nvalue\n \n=\n \nsenseair_read\n(\ntype\n);\n    \nif\n (\nvalue\n \n=\n \n0\n) {\n        \nconsole_printf\n(\nGot %d\\n\n, \nvalue\n);\n    } \nelse\n {\n        \nconsole_printf\n(\nError while reading: %d\\n\n, \nvalue\n);\n    }\n    \nreturn\n \n0\n;\n}\n\n\nint\n\n\nsenseair_init\n(\nint\n \nuartno\n)\n{\n    \nint\n \nrc\n;\n    \nstruct\n \nsenseair\n \n*s\n \n=\n \nsenseair\n;\n\n    \nrc\n \n=\n \nshell_cmd_register\n(\nsenseair_cmd\n);\n    \nif\n (\nrc\n) {\n        \nreturn\n \nrc\n;\n    }\n\n    \nrc\n \n=\n \nos_sem_init\n(\ns-\nsema\n, \n1\n);\n    \nif\n (\nrc\n) {\n        \nreturn\n \nrc\n;\n    }\n    \nrc\n \n=\n \nhal_uart_init_cbs\n(\nuartno\n, \nsenseair_tx_char\n, \nNULL\n,\n      \nsenseair_rx_char\n, \nsenseair\n);\n    \nif\n (\nrc\n) {\n        \nreturn\n \nrc\n;\n    }\n    \nrc\n \n=\n \nhal_uart_config\n(\nuartno\n, \n9600\n, \n8\n, \n1\n, \nHAL_UART_PARITY_NONE\n,\n   
    \nHAL_UART_FLOW_CTL_NONE\n);\n    \nif\n (\nrc\n) {\n        \nreturn\n \nrc\n;\n    }\n    \ns-\nuart\n \n=\n \nuartno\n;\n\n    \nreturn\n \n0\n;\n}\n\n\n\n\n\nAnd you modified your main() for senseair driver init.\n\n\nint\n\n\nmain\n(\nint\n \nargc\n, \nchar\n \n**argv\n)\n{\n    ....\n    \nsenseair_init\n(\n1\n);\n    ....\n    }\n\n\n\n\n\nYou 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.", 
+            "text": "Air quality sensor project\n\n\nSetting up source tree for stuff you need\n\n\nTo start with, you need to create a new project under which you will do this development. So you type in:\n\n\n    $ mkdir $HOME/src\n    $ cd $HOME/src\n    $ newt new air_quality\n\n\n\n\n\nLet's say you are using STM32F3discovery board 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.\n\n\nTo make this happen, you'll need to modify the project.yml in your project's root directory.\n\n\n    [user@IsMyLaptop:~/src/air_quality]$ emacs project.yml \n\n    [user@IsMyLaptop:~/src/air_quality]$ cat project.yml\n    project.name: \nair_quality\n\n\n    project.repositories:\n        - apache-mynewt-core\n        - mynewt_stm32f3\n\n    # Use github\ns distribution mechanism for core ASF libraries.\n    # This provides mirroring automatically for us.\n    #\n   
  repository.apache-mynewt-core:\n        type: github\n        vers: 0-latest\n        user: apache\n        repo: incubator-mynewt-core\n\n    repository.mynewt_stm32f3:\n        type: github\n        vers: 0-latest\n        user: runtimeinc\n        repo: mynewt_stm32f3\n    [user@IsMyLaptop:~/src/air_quality]$ newt install\n    apache-mynewt-core\n    mynewt_stm32f3\n    [user@IsMyLaptop:~/src/air_quality]$ ls repos/\n    apache-mynewt-core  mynewt_stm32f3\n\n\n\n\n\nGood. 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.\n\n\nNow 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 STM32F3Discovery board.\n\n\n[user@IsMyLaptop:~/src/air_quality]$ newt target copy my_blinky_sim blink_f3\nTarget successfully copied; targets/my_blinky_sim --\n targets/blink_f3\n[user@IsMyLaptop:~/src/air_quality]$ newt target set 
 blink_f3 bsp=@mynewt_stm32f3/hw/bsp/stm32f3discovery\nTarget targets/blink_f3 successfully set target.bsp to @mynewt_stm32f3/hw/bsp/stm32f3discovery\n[user@IsMyLaptop:~/src/air_quality]$ newt build blink_f3\nCompiling hal_bsp.c\n...\nLinking blinky.elf\nApp successfully built: /Users/user/src/air_quality/bin/blink_f3/apps/blinky/blinky.elf\n\n\n\n\n\nGood.\n\n\nYou know that this platform uses bootloader, which means you have to create a target for that too.\n\n\n[user@IsMyLaptop:~/src/air_quality]$ newt target create boot_f3\nTarget targets/boot_f3 successfully created\n[user@IsMyLaptop:~/src/air_quality]$ newt target show\n@apache-mynewt-core/targets/unittest\n    bsp=hw/bsp/native\n    build_profile=debug\n    compiler=compiler/sim\ntargets/blink_f3\n    app=apps/blinky\n    bsp=@mynewt_stm32f3/hw/bsp/stm32f3discovery\n    build_profile=debug\ntargets/boot_f3\ntargets/my_blinky_sim\n    app=apps/blinky\n    bsp=@apache-mynewt-core/hw/bsp/native\n    build_profile=debug\n[user@IsM
 yLaptop:~/src/air_quality]$ newt target set boot_f3 bsp=@mynewt_stm32f3/hw/bsp/stm32f3discovery\nTarget targets/boot_f3 successfully set target.bsp to @mynewt_stm32f3/hw/bsp/stm32f3discovery\n[user@IsMyLaptop:~/src/air_quality]$ newt target set boot_f3 app=@apache-mynewt-core/apps/boot\nTarget targets/boot_f3 successfully set target.app to @apache-mynewt-core/apps/boot\n[user@IsMyLaptop:~/src/air_quality]$ newt target set boot_f3 build_profile=optimized\nTarget targets/boot_f3 successfully set target.build_profile to optimized\n\n\n\n\n\nAnd then build it, and load it onto the board.\n\n\nnewt build boot_f3\n....\nLinking boot.elf\nApp successfully built: /Users/user/src/air_quality/bin/boot_f3/apps/boot/boot.elf\n[user@IsMyLaptop:~/src/air_quality]\n$ newt load boot_f3\n\n\n\n\n\nNext you must download the targets to board, and see that the LED actually blinks. You plug in the STM32F3 discovery board to your laptop, and say:\n\n\n[user@IsMyLaptop:~/src/air_quality]$ newt load blink
 _f3\nDownloading /Users/user/src/air_quality/bin/blink_f3/apps/blinky/blinky.img to 0x08009000\nOpen On-Chip Debugger 0.9.0 (2015-05-28-12:05)\n....\nxPSR: 0x01000000 pc: 0x0800026c msp: 0x10002000\nauto erase enabled\nError: couldn\nt open /Users/user/src/air_quality/bin/blink_f3/apps/blinky/blinky.img\n\nError: exit status 1\n\nload - Load app image to target for \ntarget-name\n.\n\nUsage:\n  newt load [flags]\n\nExamples:\n  newt load \ntarget-name\n\n\n\nGlobal Flags:\n  -l, --loglevel string   Log level, defaults to WARN. (default \nWARN\n)\n  -o, --outfile string    Filename to tee log output to\n  -q, --quiet             Be quiet; only display error output.\n  -s, --silent            Be silent; don\nt output anything.\n  -v, --verbose           Enable verbose output when executing commands.\nexit status 1\n\n\n\n\n\nAh. 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 target board, you need to run 'cre
 ate-image' on it.\n\n\n[user@IsMyLaptop:~/src/air_quality]$ newt create-image blink_f3 0.0.1\nApp image successfully generated: /Users/user/src/air_quality/bin/blink_f3/apps/blinky/blinky.img\nBuild manifest: /Users/user/src/air_quality/bin/blink_f3/apps/blinky/manifest.json\n[user@IsMyLaptop:~/src/air_quality]$ newt load blink_f3 0.0.1\n\n\n\n\n\nAnd it's blinking.\n\n\nShortcut for doing build/create-image/load/debug steps all in one is 'newt run' command. Check out the usage from command line help.\n\n\nCreate test project\n\n\nNow that you have your system setup, you can start creating your own stuff.\nFirst you want to create a project for yourself - you can start by getting project template from blinky, as it pretty much has what you want.\n\n\n    [user@IsMyLaptop:~/src/air_quality]$ mkdir apps/air_quality\n    [user@IsMyLaptop:~/src/air_quality]$ cp repos/apache-mynewt-core/apps/blinky/pkg.yml apps/air_quality/\n    [user@IsMyLaptop:~/src/air_quality]$ mkdir apps/air_quality
 /src\n    [user@IsMyLaptop:~/src/air_quality]$ cp repos/apache-mynewt-core/apps/blinky/src/main.c apps/air_quality/src/\n\n\n\n\n\nThen you modify the apps/air_quality/pkg.yml for air_quality in order to change the \npkg.name\n to be \napps/air_quality\n.\nYou also need to point the package dependencies to point to packages in apache-mynewt-core repository.\nSTM32F3discovery board has limited amount of memory, so you must also switch your libc to be baselibc, instead of the standard one.\n\n\n[user@IsMyLaptop:~/src/air_quality]$ cat apps/air_quality/pkg.yml\npkg.name: apps/air_quality\npkg.type: app\npkg.description: Air quality sensor test\npkg.keywords:\n\npkg.deps:\n    - \n@apache-mynewt-core/libs/console/full\n\n    - \n@apache-mynewt-core/libs/newtmgr\n\n    - \n@apache-mynewt-core/libs/os\n\n    - \n@apache-mynewt-core/libs/shell\n\n    - \n@apache-mynewt-core/sys/config\n\n    - \n@apache-mynewt-core/sys/log\n\n    - \n@apache-mynewt-core/sys/stats\n\n    - \n@apache-mynewt-
 core/libs/baselibc\n\n\n\n\n\n\nAnd create a target for it:\n\n\n[user@IsMyLaptop:~/src/air_quality]$ newt target create air_q\nTarget targets/air_q successfully created\n[user@IsMyLaptop:~/src/air_quality]$ newt target set air_q bsp=@mynewt_stm32f3/hw/bsp/stm32f3discovery\nTarget targets/air_q successfully set target.bsp to @mynewt_stm32f3/hw/bsp/stm32f3discovery\n[user@IsMyLaptop:~/src/air_quality]$ newt target set air_q app=apps/air_quality \nTarget targets/air_q successfully set target.app to apps/air_quality\n[user@IsMyLaptop:~/src/air_quality]$ newt target set air_q build_profile=debug\nTarget targets/air_q successfully set target.build_profile to debug\n[user@IsMyLaptop:~/src/air_quality]$ newt build air_q\n ....\nLinking air_quality.elf\nApp successfully built: /Users/user/src/air_quality/bin/air_q/apps/air_quality/air_quality.elf\n\n\n\n\n\nCreate packages for drivers\n\n\nOne of the sensors you want to enable is SenseAir K30, which will connect to the board over serial por
 t.\nTo start development of the driver, you first need to create a package description for it, and add stubs for sources.\n\n\nSo you add few files. pkg.yml to describe the driver, and then header stub followed by source stub.\n\n\n[user@IsMyLaptop:~/src/air_quality]$ cat libs/my_drivers/senseair/pkg.yml\n\n\n\n\n\n#\n\n\n# Licensed to the Apache Software Foundation (ASF) under one\n\n\n# or more contributor license agreements.  See the NOTICE file\n\n\n# distributed with this work for additional information\n\n\n# regarding copyright ownership.  The ASF licenses this file\n\n\n# to you under the Apache License, Version 2.0 (the\n\n\n# \nLicense\n); you may not use this file except in compliance\n\n\n# with the License.  You may obtain a copy of the License at\n\n\n# \n\n\n#  http:\n//www.apache.org/licenses/LICENSE-2.0\n\n\n#\n\n\n# Unless required by applicable law or agreed to in writing,\n\n\n# software distributed under the License is distributed on an\n\n\n# \nAS IS\n BASIS, W
 ITHOUT WARRANTIES OR CONDITIONS OF ANY\n\n\n# KIND, either express or implied.  See the License for the\n\n\n# specific language governing permissions and limitations\n\n\n# under the License.\n\n\n#\n\n\npkg\n.\nname\n: \nlibs/my_drivers/senseair\n\n\npkg\n.\ndeps\n:\n    \n-\n \n@apache-mynewt-core/hw/hal\n\n\n\n\n\n\n[user@IsMyLaptop:~/src/air_quality]$ cat libs/my_drivers/senseair/include/senseair/senseair.h\n\n\n\n\n\n/*\n\n\n * Licensed to the Apache Software Foundation (ASF) under one\n\n\n * or more contributor license agreements.  See the NOTICE file\n\n\n * distributed with this work for additional information\n\n\n * regarding copyright ownership.  The ASF licenses this file\n\n\n * to you under the Apache License, Version 2.0 (the\n\n\n * \nLicense\n); you may not use this file except in compliance\n\n\n * with the License.  You may obtain a copy of the License at\n\n\n * \n\n\n *  http://www.apache.org/licenses/LICENSE-2.0\n\n\n *\n\n\n * Unless required by applicable l
 aw or agreed to in writing,\n\n\n * software distributed under the License is distributed on an\n\n\n * \nAS IS\n BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n\n\n * KIND, either express or implied.  See the License for the\n\n\n * specific language governing permissions and limitations\n\n\n * under the License.\n\n\n*/\n\n\n#ifndef _SENSEAIR_H_\n\n\n#define _SENSEAIR_H_\n\n\n\nvoid\n \nsenseair_init\n(\nvoid\n);\n\n\n#endif \n/* _SENSEAIR_H_ */\n\n\n\n\n\n\n[user@IsMyLaptop:~/src/air_quality]$ cat libs/my_drivers/senseair/src/senseair.c\n\n\n\n\n\n/**\n\n\n * Licensed to the Apache Software Foundation (ASF) under one\n\n\n * or more contributor license agreements.  See the NOTICE file\n\n\n * distributed with this work for additional information\n\n\n * regarding copyright ownership.  The ASF licenses this file\n\n\n * to you under the Apache License, Version 2.0 (the\n\n\n * \nLicense\n); you may not use this file except in compliance\n\n\n * with the License.  You may obtain 
 a copy of the License at\n\n\n * \n\n\n *  http://www.apache.org/licenses/LICENSE-2.0\n\n\n *\n\n\n * Unless required by applicable law or agreed to in writing,\n\n\n * software distributed under the License is distributed on an\n\n\n * \nAS IS\n BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n\n\n * KIND, either express or implied.  See the License for the\n\n\n * specific language governing permissions and limitations\n\n\n * under the License.\n\n\n */\n\n\n\nvoid\n\n\nsenseair_init\n(\nvoid\n)\n{\n}\n\n\n\n\n\nAnd add dependency to this package in my project yml file.\n\n\nHere's from apps/air_quality/pkg.yml\n\n\npkg.name: apps/air_quality\npkg.type: app\npkg.description: Air quality sensor test\npkg.keywords:\n\npkg.deps:\n    - \n@apache-mynewt-core/libs/console/full\n\n    - \n@apache-mynewt-core/libs/newtmgr\n\n    - \n@apache-mynewt-core/libs/os\n\n    - \n@apache-mynewt-core/libs/shell\n\n    - \n@apache-mynewt-core/sys/config\n\n    - \n@apache-mynewt-core/sys/log\n\n   
  - \n@apache-mynewt-core/sys/stats\n\n    - \n@apache-mynewt-core/libs/baselibc\n\n    - libs/my_drivers/senseair\n\n\n\n\n\nAnd add a call to your main() to initialize this driver.\n\n\n    [user@IsMyLaptop:~/src/air_quality]$ diff project/blinky/src/main.c project/air_quality/src/main.c\n    28a29\n    \n #include \nsenseair/senseair.h\n\n    190a192\n    \n senseair_init();\n    [user@IsMyLaptop:~/src/air_quality\n\n\n\n\n\nAnd then build it to make sure all goes well.\n\n\n[user@IsMyLaptop:~/src/air_quality]$ newt build air_q\nCompiling senseair.c\nArchiving senseair.a\nLinking air_quality.elf\nApp successfully built: /Users/user/src/air_quality/bin/air_q/apps/air_quality/air_quality.elf\n\n\n\n\n\nAll looks good.\n\n\nAdd CLI commands for testing drivers\n\n\nWhile developing the driver, you want to issue operations from console asking it to do stuff. The way to do this is to register your command handler with shell. Whenever your custom command is issued, you can respond to it
 .\n\n\nThe way you do this is first adding a dependency to shell package for your senseair driver. So you change libs/my_drivers/senseair/pkg.yml to have the following:\n\n\npkg.name: libs/my_drivers/senseair\npkg.deps:\n    - \n@apache-mynewt-core/hw/hal\n\n    - \n@apache-mynewt-core/libs/shell\n\n\n\n\n\n\nAnd then register your shell command in \nsenseair_init()\n.\n\n\n[user@IsMyLaptop:~/src/air_quality]$ cat libs/my_drivers/senseair/src/senseair.c\n ....\n\n\n\n\n\n#include \nshell/shell.h\n\n\n#include \nconsole/console.h\n\n\n\nstatic\n \nint\n \nsenseair_shell_func\n(\nint\n \nargc\n, \nchar\n \n**argv\n);\n\nstatic\n \nstruct\n \nshell_cmd\n \nsenseair_cmd\n \n=\n {\n    .\nsc_cmd\n \n=\n \nsenseair\n,\n    .\nsc_cmd_func\n \n=\n \nsenseair_shell_func\n,\n};\n\n\nvoid\n\n\nsenseair_init\n(\nvoid\n)\n{\n    \nint\n \nrc\n;\n\n    \nrc\n \n=\n \nshell_cmd_register\n(\nsenseair_cmd\n);\n    \nassert\n(\nrc\n \n==\n \n0\n);\n}\n\n\nstatic\n \nint\n\n\nsenseair_shell_func\n(\ni
 nt\n \nargc\n, \nchar\n \n**argv\n)\n{\n    \nconsole_printf\n(\nYay! Somebody called!\\n\n);\n    \nreturn\n \n0\n;\n}\n\n\n\n\n\nThen you build this, download to target, and start minicom on your console port.\n\n\nYou'll need to wire up your Board to a Serial converter first. On the STM32F3-Discovery Board pin PA9 is TX and pin PA10 is RX so wire PA9 to RX on your serial board, and PA10 to TX on your serial board.\n\n\n    [user@IsMyLaptop:~]$ minicom -D /dev/tty.usbserial-AH02MIE2\n\n\n    Welcome to minicom 2.7\n\n    OPTIONS: \n    Compiled on Oct 12 2015, 07:48:30.\n    Port /dev/tty.usbserial-AH02MIE2, 13:44:40\n\n    Press CTRL-X Z for help on special keys\n\n    ?\n    141964:Unknown command ?\n    ?\n    143804:config   log     echo    ?       tasks   mempools \n    143806:stat     senseair \n    senseair\n    150644:Yay! Somebody called!\n\n\n\n\n\nNow that's great. You can connect the hardware to board and start developing code for the driver itself.\n\n\nUse of HAL for
  drivers\n\n\nThe sensor has a serial port connection, and that's how you are going to connect to it. Your original BSP, hw/bsp/stm32f3discovery, has only one UART set up (as specified in src/hal_bsp.c, include/hal/bsp.h). Therefore, you need to create your own bsp which has configuration for this added hardware.\n\n\nSo in the shell you make a copy of the original BSP, and then change the package file a little.\n\n\n[user@IsMyLaptop:~/src/air_quality]$ mkdir hw\n[user@IsMyLaptop:~/src/air_quality]$ mkdir hw/bsp\n\n[user@IsMyLaptop:~/src/air_quality]$ cp -R repos/mynewt_stm32f3/hw/bsp/stm32f3discovery hw/bsp/stm32f3discovery_with_senseair\n\n\n\n\n\nThen you modify the pkg.yml in the copied BSP to assign name for this package. And modify the dependency for MCU package to point to mynewt_stm32f3 repository.\n\n\n    [user@IsMyLaptop:~/src/air_quality]$ grep pkg.name hw/bsp/stm32f3discovery_with_senseair/pkg.yml\n    pkg.name: \nhw/bsp/stm32f3discovery_with_senseair\n\n    [user@IsMyL
 aptop:~/src/air_quality]$ tail -2 hw/bsp/stm32f3discovery_with_senseair/pkg.yml\npkg.deps:\n    - \n@mynewt_stm32f3/hw/mcu/stm/stm32f3xx\n\n\n\n\n\n\nAnd you want to use this BSP with my target. So you change the BSP in the target definition.\n\n\nHere's your new target.\n\n\n[user@IsMyLaptop:~/src/air_quality]$ newt target show air_q\ntargets/air_q\n    app=apps/air_quality\n    bsp=hw/bsp/stm32f3discovery_with_senseair\n    build_profile=debug\n\n\n\n\n\nYou add the 2nd serial port to my new BSP. Go to hw/bsp/stm32f3discovery_with_senseair directory to do this.\n\n\nModify the include/hal/bsp.h to increase UART_CNT to 2, and add a definition of the 2nd logical UART. You will use this in your sensor driver.\n\n\nstatic\n \nconst\n \nstruct\n \nstm32f3_uart_cfg\n \nuart_cfg\n[\nUART_CNT\n] \n=\n {\n    [\n0\n] \n=\n {\n        .\nsuc_uart\n \n=\n \nUSART1\n,\n        .\nsuc_rcc_cmd\n \n=\n \nRCC_APB2PeriphClockCmd\n,\n        .\nsuc_rcc_dev\n \n=\n \nRCC_APB2Periph_USART1\n,\n      
   .\nsuc_pin_tx\n \n=\n \n9\n,\n        .\nsuc_pin_rx\n \n=\n \n10\n,\n        .\nsuc_pin_rts\n \n=\n \n12\n,\n        .\nsuc_pin_cts\n \n=\n \n11\n,\n        .\nsuc_pin_af\n \n=\n \nGPIO_AF_7\n,\n        .\nsuc_irqn\n \n=\n \nUSART1_IRQn\n\n    },\n    [\n1\n] \n=\n {\n        .\nsuc_uart\n \n=\n \nUSART2\n,\n        .\nsuc_rcc_cmd\n \n=\n \nRCC_APB1PeriphClockCmd\n,\n        .\nsuc_rcc_dev\n \n=\n \nRCC_APB1Periph_USART2\n,\n        .\nsuc_pin_tx\n \n=\n \n19\n, \n/* PB3 */\n\n        .\nsuc_pin_rx\n \n=\n \n20\n, \n/* PB4 */\n\n        .\nsuc_pin_rts\n \n=\n \n1\n,\n        .\nsuc_pin_cts\n \n=\n \n0\n,\n        .\nsuc_pin_af\n \n=\n \nGPIO_AF_7\n,\n        .\nsuc_irqn\n \n=\n \nUSART2_IRQn\n\n    }\n};\n\n\n\n\n\nWith this in place, you can refer to serial port where your SenseAir sensor is 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 por
 t setup and data transfer. That way you don't need to have any platform dependent pieces within your little driver.\n\n\nYou will now see what the driver code ends up looking like. Here's the header file, filled in from stub you created earlier.\n\n\n/*\n\n\n * Licensed to the Apache Software Foundation (ASF) under one\n\n\n * or more contributor license agreements.  See the NOTICE file\n\n\n * distributed with this work for additional information\n\n\n * regarding copyright ownership.  The ASF licenses this file\n\n\n * to you under the Apache License, Version 2.0 (the\n\n\n * \nLicense\n); you may not use this file except in compliance\n\n\n * with the License.  You may obtain a copy of the License at\n\n\n * \n\n\n *  http://www.apache.org/licenses/LICENSE-2.0\n\n\n *\n\n\n * Unless required by applicable law or agreed to in writing,\n\n\n * software distributed under the License is distributed on an\n\n\n * \nAS IS\n BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n\n\n * KIND, e
 ither express or implied.  See the License for the\n\n\n * specific language governing permissions and limitations\n\n\n * under the License.\n\n\n*/\n\n\n#ifndef _SENSEAIR_H_\n\n\n#define _SENSEAIR_H_\n\n\n\nenum\n \nsenseair_read_type\n {\n        \nSENSEAIR_CO2\n,\n        \nSENSEAIR_TEMPERATURE\n,\n        \nSENSEAIR_HUMIDITY\n\n};\n\n\nint\n \nsenseair_init\n(\nint\n \nuartno\n);\n\n\nint\n \nsenseair_read\n(\nenum\n \nsenseair_read_type\n);\n\n\n#endif \n/* _SENSEAIR_H_ */\n\n\n\n\n\n\nAs 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.\n\n\nAnd here is the source for the driver.\n\n\n/**\n\n\n * Licensed to the Apache Software Foundation (ASF) under one\n\n\n * or more contributor license agreements.  See the NOTICE file\n\n\n * distributed with this work for additional information\n\n\n * regard
 ing copyright ownership.  The ASF licenses this file\n\n\n * to you under the Apache License, Version 2.0 (the\n\n\n * \nLicense\n); you may not use this file except in compliance\n\n\n * with the License.  You may obtain a copy of the License at\n\n\n *\n\n\n *  http://www.apache.org/licenses/LICENSE-2.0\n\n\n *\n\n\n * Unless required by applicable law or agreed to in writing,\n\n\n * software distributed under the License is distributed on an\n\n\n * \nAS IS\n BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n\n\n * KIND, either express or implied.  See the License for the\n\n\n * specific language governing permissions and limitations\n\n\n * under the License.\n\n\n */\n\n\n#include \nstring.h\n\n\n\n#include \nshell/shell.h\n\n\n#include \nconsole/console.h\n\n\n#include \nos/os.h\n\n\n\n#include \nhal/hal_uart.h\n\n\n\n#include \nsenseair/senseair.h\n\n\n\nstatic\n \nconst\n \nuint8_t\n \ncmd_read_co2\n[] \n=\n {\n    \n0xFE\n, \n0\nX44\n, \n0\nX00\n, \n0\nX08\n, \n0\nX02\n, \n
 0\nX9F\n, \n0\nX25\n\n};\n\nstatic\n \nconst\n \nuint8_t\n \ncmd_read_temp\n[] \n=\n {\n    \n0xFE\n, \n0\nX44\n, \n0\nX00\n, \n0\nX12\n, \n0\nX02\n, \n0\nX94\n, \n0\nX45\n\n};\n\nstatic\n \nconst\n \nuint8_t\n \ncmd_read_humidity\n[] \n=\n {\n    \n0xFE\n, \n0x44\n, \n0x00\n, \n0x14\n, \n0x02\n, \n0x97\n, \n0xE5\n\n};\n\n\nstatic\n \nint\n \nsenseair_shell_func\n(\nint\n \nargc\n, \nchar\n \n**argv\n);\n\nstatic\n \nstruct\n \nshell_cmd\n \nsenseair_cmd\n \n=\n {\n    .\nsc_cmd\n \n=\n \nsenseair\n,\n    .\nsc_cmd_func\n \n=\n \nsenseair_shell_func\n,\n};\n\n\nstruct\n \nsenseair\n { \n    \nint\n \nuart\n;\n    \nstruct\n \nos_sem\n \nsema\n;\n    \nconst\n \nuint8_t\n \n*tx_data\n;\n    \nint\n \ntx_off\n;\n    \nint\n \ntx_len\n;\n    \nuint8_t\n \nrx_data\n[\n32\n]; \n    \nint\n \nrx_off\n;\n    \nint\n \nvalue\n;\n} \nsenseair\n;\n\n\nstatic\n \nint\n\n\nsenseair_tx_char\n(\nvoid\n \n*arg\n)\n{\n    \nstruct\n \nsenseair\n \n*s\n \n=\n \nsenseair\n;\n    \nint\n \nrc\n;\n\n  
   \nif\n (\ns-\ntx_off\n \n=\n \ns-\ntx_len\n) {\n    \n/*\n\n\n         * Command tx finished.\n\n\n         */\n\n        \ns-\ntx_data\n \n=\n \nNULL\n;\n        \nreturn\n \n-\n1\n;\n    }\n\n    \nrc\n \n=\n \ns-\ntx_data\n[\ns-\ntx_off\n];\n    \ns-\ntx_off++\n;\n    \nreturn\n \nrc\n;\n}\n\n\n/*\n\n\n * CRC for modbus over serial port.\n\n\n */\n\n\nstatic\n \nconst\n \nuint16_t\n \nmb_crc_tbl\n[] \n=\n {\n    \n0x0000\n, \n0xcc01\n, \n0xd801\n, \n0x1400\n, \n0xf001\n, \n0x3c00\n, \n0x2800\n, \n0xe401\n,\n    \n0xa001\n, \n0x6c00\n, \n0x7800\n, \n0xb401\n, \n0x5000\n, \n0x9c01\n, \n0x8801\n, \n0x4400\n\n};\n\n\nstatic\n \nuint16_t\n\n\nmb_crc\n(\nconst\n \nuint8_t\n \n*data\n, \nint\n \nlen\n, \nuint16_t\n \ncrc\n)\n{\n    \nwhile\n (\nlen--\n \n \n0\n) {\n        \ncrc\n \n^=\n \n*data++\n;\n        \ncrc\n \n=\n (\ncrc\n \n \n4\n) \n^\n \nmb_crc_tbl\n[\ncrc\n \n \n0xf\n];\n        \ncrc\n \n=\n (\ncrc\n \n \n4\n) \n^\n \nmb_crc_tbl\n[\ncrc\n \n \n0xf\n];\n    }\n    \nretur
 n\n \ncrc\n;\n}\n\n\nstatic\n \nint\n\n\nmb_crc_check\n(\nconst\n \nvoid\n \n*pkt\n, \nint\n \nlen\n)\n{\n    \nuint16_t\n \ncrc\n, \ncmp\n;\n    \nuint8_t\n \n*bp\n \n=\n (\nuint8_t\n \n*\n)\npkt\n;\n\n    \nif\n (\nlen\n \n \nsizeof\n(\ncrc\n) \n+\n \n1\n) {\n        \nreturn\n \n-\n1\n;\n    }\n    \ncrc\n \n=\n \nmb_crc\n(\npkt\n, \nlen\n \n-\n \n2\n, \n0xffff\n);\n    \ncmp\n \n=\n \nbp\n[\nlen\n \n-\n \n2\n] \n|\n (\nbp\n[\nlen\n \n-\n \n1\n] \n \n8\n);\n    \nif\n (\ncrc\n \n!=\n \ncmp\n) {\n        \nreturn\n \n-\n1\n;\n    } \nelse\n {\n        \nreturn\n \n0\n;\n    }\n}\n\n\nstatic\n \nint\n\n\nsenseair_rx_char\n(\nvoid\n \n*arg\n, \nuint8_t\n \ndata\n)\n{\n    \nstruct\n \nsenseair\n \n*s\n \n=\n (\nstruct\n \nsenseair\n \n*\n)\narg\n;\n    \nint\n \nrc\n;\n\n    \nif\n (\ns-\nrx_off\n \n=\n \nsizeof\n(\ns-\nrx_data\n)) {\n        \ns-\nrx_off\n \n=\n \n0\n;\n    }\n    \ns-\nrx_data\n[\ns-\nrx_off\n] \n=\n \ndata\n;\n    \ns-\nrx_off++\n;\n\n    \nif\n (\ns-\nrx_off\n \
 n==\n \n7\n) {\n        \nrc\n \n=\n \nmb_crc_check\n(\ns-\nrx_data\n, \ns-\nrx_off\n);\n        \nif\n (\nrc\n \n==\n \n0\n) {\n            \ns-\nvalue\n \n=\n \ns-\nrx_data\n[\n3\n] \n*\n \n256\n \n+\n \ns-\nrx_data\n[\n4\n];\n            \nos_sem_release\n(\ns-\nsema\n);\n        }\n    }\n    \nreturn\n \n0\n;\n}\n\n\nvoid\n\n\nsenseair_tx\n(\nstruct\n \nsenseair\n \n*s\n, \nconst\n \nuint8_t\n \n*tx_data\n, \nint\n \ndata_len\n)\n{\n    \ns-\ntx_data\n \n=\n \ntx_data\n;\n    \ns-\ntx_len\n \n=\n \ndata_len\n;\n    \ns-\ntx_off\n \n=\n \n0\n;\n    \ns-\nrx_off\n \n=\n \n0\n;\n\n    \nhal_uart_start_tx\n(\ns-\nuart\n);\n}\n\n\nint\n\n\nsenseair_read\n(\nenum\n \nsenseair_read_type\n \ntype\n)\n{\n    \nstruct\n \nsenseair\n \n*s\n \n=\n \nsenseair\n;\n    \nconst\n \nuint8_t\n \n*cmd\n;\n    \nint\n \ncmd_len\n;\n    \nint\n \nrc\n;\n\n    \nif\n (\ns-\ntx_data\n) {\n        \n/*\n\n\n         * busy\n\n\n         */\n\n        \nreturn\n \n-\n1\n;\n    }\n    \nswitch\n (\ntype
 \n) {\n    \ncase\n \nSENSEAIR_CO2\n:\n        \ncmd\n \n=\n \ncmd_read_co2\n;\n        \ncmd_len\n \n=\n \nsizeof\n(\ncmd_read_co2\n);\n        \nbreak\n;\n    \ncase\n \nSENSEAIR_TEMPERATURE\n:\n        \ncmd\n \n=\n \ncmd_read_temp\n;\n        \ncmd_len\n \n=\n \nsizeof\n(\ncmd_read_temp\n);\n        \nbreak\n;\n    \ncase\n \nSENSEAIR_HUMIDITY\n:\n        \ncmd\n \n=\n \ncmd_read_humidity\n;\n        \ncmd_len\n \n=\n \nsizeof\n(\ncmd_read_humidity\n);\n        \nbreak\n;\n    \ndefault\n:\n\n        \nreturn\n \n-\n1\n;\n    }\n    \nsenseair_tx\n(\ns\n, \ncmd\n, \ncmd_len\n);\n    \nrc\n \n=\n \nos_sem_pend\n(\ns-\nsema\n, \nOS_TICKS_PER_SEC\n \n/\n \n2\n);\n    \nif\n (\nrc\n \n==\n \nOS_TIMEOUT\n) {\n        \n/*\n\n\n         * timeout\n\n\n         */\n\n        \nreturn\n \n-\n2\n;\n    }\n    \nreturn\n \ns-\nvalue\n;\n}\n\n\nstatic\n \nint\n\n\nsenseair_shell_func\n(\nint\n \nargc\n, \nchar\n \n**argv\n)\n{\n    \nint\n \nvalue\n;\n    \nenum\n \nsenseair_read_type\n \n
 type\n;\n\n    \nif\n (\nargc\n \n \n2\n) {\n\nusage\n:\n        \nconsole_printf\n(\n%s \nco2|temp|humidity\n\\n\n, \nargv\n[\n0\n]);\n        \nreturn\n \n0\n;\n    }\n    \nif\n (\n!strcmp\n(\nargv\n[\n1\n], \nco2\n)) {\n        \ntype\n \n=\n \nSENSEAIR_CO2\n;\n    } \nelse\n \nif\n (\n!strcmp\n(\nargv\n[\n1\n], \ntemp\n)) {\n        \ntype\n \n=\n \nSENSEAIR_TEMPERATURE\n;\n    } \nelse\n \nif\n (\n!strcmp\n(\nargv\n[\n1\n], \nhumidity\n)) {\n        \n/*\n\n\n         * timeout\n\n\n         */\n\n        \nreturn\n \n-\n2\n;\n    }\n    \nreturn\n \ns-\nvalue\n;\n}\n\n\nstatic\n \nint\n\n\nsenseair_shell_func\n(\nint\n \nargc\n, \nchar\n \n**argv\n)\n{\n    \nint\n \nvalue\n;\n    \nenum\n \nsenseair_read_type\n \ntype\n;\n\n    \nif\n (\nargc\n \n \n2\n) {\n\nusage\n:\n        \nconsole_printf\n(\n%s \nco2|temp|humidity\n\\n\n, \nargv\n[\n0\n]);\n        \nreturn\n \n0\n;\n    }\n    \nif\n (\n!strcmp\n(\nargv\n[\n1\n], \nco2\n)) {\n        \ntype\n \n=\n \nSENSEAIR_CO2\n;\n
     } \nelse\n \nif\n (\n!strcmp\n(\nargv\n[\n1\n], \ntemp\n)) {\n        \ntype\n \n=\n \nSENSEAIR_TEMPERATURE\n;\n    } \nelse\n \nif\n (\n!strcmp\n(\nargv\n[\n1\n], \nhumidity\n)) {\n        \ntype\n \n=\n \nSENSEAIR_HUMIDITY\n;\n    } \nelse\n {\n        \ngoto\n \nusage\n;\n    }\n    \nvalue\n \n=\n \nsenseair_read\n(\ntype\n);\n    \nif\n (\nvalue\n \n=\n \n0\n) {\n        \nconsole_printf\n(\nGot %d\\n\n, \nvalue\n);\n    } \nelse\n {\n        \nconsole_printf\n(\nError while reading: %d\\n\n, \nvalue\n);\n    }\n    \nreturn\n \n0\n;\n}\n\n\nint\n\n\nsenseair_init\n(\nint\n \nuartno\n)\n{\n    \nint\n \nrc\n;\n    \nstruct\n \nsenseair\n \n*s\n \n=\n \nsenseair\n;\n\n    \nrc\n \n=\n \nshell_cmd_register\n(\nsenseair_cmd\n);\n    \nif\n (\nrc\n) {\n        \nreturn\n \nrc\n;\n    }\n\n    \nrc\n \n=\n \nos_sem_init\n(\ns-\nsema\n, \n1\n);\n    \nif\n (\nrc\n) {\n        \nreturn\n \nrc\n;\n    }\n    \nrc\n \n=\n \nhal_uart_init_cbs\n(\nuartno\n, \nsenseair_tx_char\n, \nNUL
 L\n,\n      \nsenseair_rx_char\n, \nsenseair\n);\n    \nif\n (\nrc\n) {\n        \nreturn\n \nrc\n;\n    }\n    \nrc\n \n=\n \nhal_uart_config\n(\nuartno\n, \n9600\n, \n8\n, \n1\n, \nHAL_UART_PARITY_NONE\n,\n      \nHAL_UART_FLOW_CTL_NONE\n);\n    \nif\n (\nrc\n) {\n        \nreturn\n \nrc\n;\n    }\n    \ns-\nuart\n \n=\n \nuartno\n;\n\n    \nreturn\n \n0\n;\n}\n\n\n\n\n\nAnd you modified your main() for senseair driver init.\n\n\nint\n\n\nmain\n(\nint\n \nargc\n, \nchar\n \n**argv\n)\n{\n    ....\n    \nsenseair_init\n(\n1\n);\n    ....\n    }\n\n\n\n\n\nYou 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.", 
             "title": "Air-quality Sensor project"
         }, 
         {
@@ -997,7 +997,7 @@
         }, 
         {
             "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\n    $ cd $HOME/src\n    $ newt new air_quality  Let's say you are using STM32F3discovery board 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.  To make this happen, you'll need to modify the project.yml in your project's root directory.      [user@IsMyLaptop:~/src/air_quality]$ emacs project.yml  \n    [user@IsMyLaptop:~/src/air_quality]$ cat project.yml\n    project.name:  air_quality \n\n    project.repositories:\n        - apache-mynewt-core\n        - mynewt_stm32f3\n\n    # Use github s distribution mechanism for core ASF libraries.\n    # This provides mirroring automatically for us.\n    #\n    repository.apache-mynewt-core:\n        type: github\n        vers: 0-latest\n        user: apache\n    
     repo: incubator-mynewt-core\n\n    repository.mynewt_stm32f3:\n        type: github\n        vers: 0-latest\n        user: runtimeinc\n        repo: mynewt_stm32f3\n    [user@IsMyLaptop:~/src/air_quality]$ newt install\n    apache-mynewt-core\n    mynewt_stm32f3\n    [user@IsMyLaptop:~/src/air_quality]$ ls repos/\n    apache-mynewt-core  mynewt_stm32f3  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 STM32F3Discovery board.  [user@IsMyLaptop:~/src/air_quality]$ newt target copy my_blinky_sim blink_f3\nTarget successfully copied; targets/my_blinky_sim --  targets/blink_f3\n[user@IsMyLaptop:~/src/air_quality]$ newt target set blink_f3 bsp=@mynewt_stm32f3/hw/bsp/stm32f3discovery\nTarget targets/blink_f3 successfully set target.bsp to @mynewt_stm32f3
 /hw/bsp/stm32f3discovery\n[user@IsMyLaptop:~/src/air_quality]$ newt build blink_f3\nCompiling hal_bsp.c\n...\nLinking blinky.elf\nApp successfully built: /Users/user/src/air_quality/bin/blink_f3/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_f3\nTarget targets/boot_f3 successfully created\n[user@IsMyLaptop:~/src/air_quality]$ newt target show\n@apache-mynewt-core/targets/unittest\n    bsp=hw/bsp/native\n    build_profile=debug\n    compiler=compiler/sim\ntargets/blink_f3\n    app=apps/blinky\n    bsp=@mynewt_stm32f3/hw/bsp/stm32f3discovery\n    build_profile=debug\ntargets/boot_f3\ntargets/my_blinky_sim\n    app=apps/blinky\n    bsp=@apache-mynewt-core/hw/bsp/native\n    build_profile=debug\n[user@IsMyLaptop:~/src/air_quality]$ newt target set boot_f3 bsp=@mynewt_stm32f3/hw/bsp/stm32f3discovery\nTarget targets/boot_f3 successfully set targe
 t.bsp to @mynewt_stm32f3/hw/bsp/stm32f3discovery\n[user@IsMyLaptop:~/src/air_quality]$ newt target set boot_f3 app=@apache-mynewt-core/apps/boot\nTarget targets/boot_f3 successfully set target.app to @apache-mynewt-core/apps/boot\n[user@IsMyLaptop:~/src/air_quality]$ newt target set boot_f3 build_profile=optimized\nTarget targets/boot_f3 successfully set target.build_profile to optimized  And then build it, and load it onto the board.  newt build boot_f3\n....\nLinking boot.elf\nApp successfully built: /Users/user/src/air_quality/bin/boot_f3/apps/boot/boot.elf\n[user@IsMyLaptop:~/src/air_quality]$ newt load boot_f3  Next you must download the targets to board, and see that the LED actually blinks. You plug in the STM32F3 discovery board to your laptop, and say:  [user@IsMyLaptop:~/src/air_quality]$ newt load blink_f3\nDownloading /Users/user/src/air_quality/bin/blink_f3/apps/blinky/blinky.img to 0x08009000\nOpen On-Chip Debugger 0.9.0 (2015-05-28-12:05)\n....\nxPSR: 0x01000000 pc: 0
 x0800026c msp: 0x10002000\nauto erase enabled\nError: couldn t open /Users/user/src/air_quality/bin/blink_f3/apps/blinky/blinky.img\n\nError: exit status 1\n\nload - Load app image to target for  target-name .\n\nUsage:\n  newt load [flags]\n\nExamples:\n  newt load  target-name \n\n\nGlobal Flags:\n  -l, --loglevel string   Log level, defaults to WARN. (default  WARN )\n  -o, --outfile string    Filename to tee log output to\n  -q, --quiet             Be quiet; only display error output.\n  -s, --silent            Be silent; don t output anything.\n  -v, --verbose           Enable verbose output when executing commands.\nexit 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 target board, you need to run 'create-image' on it.  [user@IsMyLaptop:~/src/air_quality]$ newt create-image blink_f3 0.0.1\nApp image successfully generated: /Users/user/src/air_quality/bin/blink_f3/apps/blinky/blinky.img\nB
 uild manifest: /Users/user/src/air_quality/bin/blink_f3/apps/blinky/manifest.json\n[user@IsMyLaptop:~/src/air_quality]$ newt load blink_f3 0.0.1  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.", 
+            "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\n    $ cd $HOME/src\n    $ newt new air_quality  Let's say you are using STM32F3discovery board 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.  To make this happen, you'll need to modify the project.yml in your project's root directory.      [user@IsMyLaptop:~/src/air_quality]$ emacs project.yml  \n    [user@IsMyLaptop:~/src/air_quality]$ cat project.yml\n    project.name:  air_quality \n\n    project.repositories:\n        - apache-mynewt-core\n        - mynewt_stm32f3\n\n    # Use github s distribution mechanism for core ASF libraries.\n    # This provides mirroring automatically for us.\n    #\n    repository.apache-mynewt-core:\n        type: github\n        vers: 0-latest\n        user: apache\n    
     repo: incubator-mynewt-core\n\n    repository.mynewt_stm32f3:\n        type: github\n        vers: 0-latest\n        user: runtimeinc\n        repo: mynewt_stm32f3\n    [user@IsMyLaptop:~/src/air_quality]$ newt install\n    apache-mynewt-core\n    mynewt_stm32f3\n    [user@IsMyLaptop:~/src/air_quality]$ ls repos/\n    apache-mynewt-core  mynewt_stm32f3  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 STM32F3Discovery board.  [user@IsMyLaptop:~/src/air_quality]$ newt target copy my_blinky_sim blink_f3\nTarget successfully copied; targets/my_blinky_sim --  targets/blink_f3\n[user@IsMyLaptop:~/src/air_quality]$ newt target set blink_f3 bsp=@mynewt_stm32f3/hw/bsp/stm32f3discovery\nTarget targets/blink_f3 successfully set target.bsp to @mynewt_stm32f3
 /hw/bsp/stm32f3discovery\n[user@IsMyLaptop:~/src/air_quality]$ newt build blink_f3\nCompiling hal_bsp.c\n...\nLinking blinky.elf\nApp successfully built: /Users/user/src/air_quality/bin/blink_f3/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_f3\nTarget targets/boot_f3 successfully created\n[user@IsMyLaptop:~/src/air_quality]$ newt target show\n@apache-mynewt-core/targets/unittest\n    bsp=hw/bsp/native\n    build_profile=debug\n    compiler=compiler/sim\ntargets/blink_f3\n    app=apps/blinky\n    bsp=@mynewt_stm32f3/hw/bsp/stm32f3discovery\n    build_profile=debug\ntargets/boot_f3\ntargets/my_blinky_sim\n    app=apps/blinky\n    bsp=@apache-mynewt-core/hw/bsp/native\n    build_profile=debug\n[user@IsMyLaptop:~/src/air_quality]$ newt target set boot_f3 bsp=@mynewt_stm32f3/hw/bsp/stm32f3discovery\nTarget targets/boot_f3 successfully set targe
 t.bsp to @mynewt_stm32f3/hw/bsp/stm32f3discovery\n[user@IsMyLaptop:~/src/air_quality]$ newt target set boot_f3 app=@apache-mynewt-core/apps/boot\nTarget targets/boot_f3 successfully set target.app to @apache-mynewt-core/apps/boot\n[user@IsMyLaptop:~/src/air_quality]$ newt target set boot_f3 build_profile=optimized\nTarget targets/boot_f3 successfully set target.build_profile to optimized  And then build it, and load it onto the board.  newt build boot_f3\n....\nLinking boot.elf\nApp successfully built: /Users/user/src/air_quality/bin/boot_f3/apps/boot/boot.elf\n[user@IsMyLaptop:~/src/air_quality]\n$ newt load boot_f3  Next you must download the targets to board, and see that the LED actually blinks. You plug in the STM32F3 discovery board to your laptop, and say:  [user@IsMyLaptop:~/src/air_quality]$ newt load blink_f3\nDownloading /Users/user/src/air_quality/bin/blink_f3/apps/blinky/blinky.img to 0x08009000\nOpen On-Chip Debugger 0.9.0 (2015-05-28-12:05)\n....\nxPSR: 0x01000000 pc:
  0x0800026c msp: 0x10002000\nauto erase enabled\nError: couldn t open /Users/user/src/air_quality/bin/blink_f3/apps/blinky/blinky.img\n\nError: exit status 1\n\nload - Load app image to target for  target-name .\n\nUsage:\n  newt load [flags]\n\nExamples:\n  newt load  target-name \n\n\nGlobal Flags:\n  -l, --loglevel string   Log level, defaults to WARN. (default  WARN )\n  -o, --outfile string    Filename to tee log output to\n  -q, --quiet             Be quiet; only display error output.\n  -s, --silent            Be silent; don t output anything.\n  -v, --verbose           Enable verbose output when executing commands.\nexit 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 target board, you need to run 'create-image' on it.  [user@IsMyLaptop:~/src/air_quality]$ newt create-image blink_f3 0.0.1\nApp image successfully generated: /Users/user/src/air_quality/bin/blink_f3/apps/blinky/blinky.img\
 nBuild manifest: /Users/user/src/air_quality/bin/blink_f3/apps/blinky/manifest.json\n[user@IsMyLaptop:~/src/air_quality]$ newt load blink_f3 0.0.1  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"
         }, 
         {
@@ -1012,7 +1012,7 @@
         }, 
         {
             "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. The way to do this is to register your command handler with shell. Whenever your custom command is issued, you can respond to it.  The way you do this is first adding a dependency to shell package for your senseair driver. So you change libs/my_drivers/senseair/pkg.yml to have the following:  pkg.name: libs/my_drivers/senseair\npkg.deps:\n    -  @apache-mynewt-core/hw/hal \n    -  @apache-mynewt-core/libs/shell   And then register your shell command in  senseair_init() .  [user@IsMyLaptop:~/src/air_quality]$ cat libs/my_drivers/senseair/src/senseair.c\n ....  #include  shell/shell.h  #include  console/console.h  static   int   senseair_shell_func ( int   argc ,  char   **argv ); static   struct   shell_cmd   senseair_cmd   =  {\n    . sc_cmd   =   senseair ,\n    . sc_cmd_func   =   senseair_shell_func ,\n}; void  senseair_init ( void )\n{\n     int   rc ;\n\n     rc   
 =   shell_cmd_register ( senseair_cmd );\n     assert ( rc   ==   0 );\n} static   int  senseair_shell_func ( int   argc ,  char   **argv )\n{\n     console_printf ( Yay! Somebody called!\\n );\n     return   0 ;\n}  Then you build this, download to target, and start minicom on your console port.      [user@IsMyLaptop:~]$ minicom -D /dev/tty.usbserial-AH02MIE2\n\n\n    Welcome to minicom 2.7\n\n    OPTIONS: \n    Compiled on Oct 12 2015, 07:48:30.\n    Port /dev/tty.usbserial-AH02MIE2, 13:44:40\n\n    Press CTRL-X Z for help on special keys\n\n    ?\n    141964:Unknown command ?\n    ?\n    143804:config   log     echo    ?       tasks   mempools \n    143806:stat     senseair \n    senseair\n    150644:Yay! Somebody called!  Now that's great. You can connect the hardware to board and start developing code for the driver itself.", 
+            "text": "While developing the driver, you want to issue operations from console asking it to do stuff. The way to do this is to register your command handler with shell. Whenever your custom command is issued, you can respond to it.  The way you do this is first adding a dependency to shell package for your senseair driver. So you change libs/my_drivers/senseair/pkg.yml to have the following:  pkg.name: libs/my_drivers/senseair\npkg.deps:\n    -  @apache-mynewt-core/hw/hal \n    -  @apache-mynewt-core/libs/shell   And then register your shell command in  senseair_init() .  [user@IsMyLaptop:~/src/air_quality]$ cat libs/my_drivers/senseair/src/senseair.c\n ....  #include  shell/shell.h  #include  console/console.h  static   int   senseair_shell_func ( int   argc ,  char   **argv ); static   struct   shell_cmd   senseair_cmd   =  {\n    . sc_cmd   =   senseair ,\n    . sc_cmd_func   =   senseair_shell_func ,\n}; void  senseair_init ( void )\n{\n     int   rc ;\n\n     rc   
 =   shell_cmd_register ( senseair_cmd );\n     assert ( rc   ==   0 );\n} static   int  senseair_shell_func ( int   argc ,  char   **argv )\n{\n     console_printf ( Yay! Somebody called!\\n );\n     return   0 ;\n}  Then you build this, download to target, and start minicom on your console port.  You'll need to wire up your Board to a Serial converter first. On the STM32F3-Discovery Board pin PA9 is TX and pin PA10 is RX so wire PA9 to RX on your serial board, and PA10 to TX on your serial board.      [user@IsMyLaptop:~]$ minicom -D /dev/tty.usbserial-AH02MIE2\n\n\n    Welcome to minicom 2.7\n\n    OPTIONS: \n    Compiled on Oct 12 2015, 07:48:30.\n    Port /dev/tty.usbserial-AH02MIE2, 13:44:40\n\n    Press CTRL-X Z for help on special keys\n\n    ?\n    141964:Unknown command ?\n    ?\n    143804:config   log     echo    ?       tasks   mempools \n    143806:stat     senseair \n    senseair\n    150644:Yay! Somebody called!  Now that's great. You can connect the hardware to board 
 and start developing code for the driver itself.", 
             "title": "Add CLI commands for testing drivers"
         }, 
         {
@@ -1212,7 +1212,7 @@
         }, 
         {
             "location": "/os/tutorials/bletiny_project/", 
-            "text": "Check stats on a BLE device\n\n\n\n\nThis 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.\n\n\n\n\nPre-Requisites\n\n\n\n\nEnsure you have installed \nnewt\n and that the \nnewt command is in your system path. \n\n\nYou must have Internet connectivity to fetch remote Mynewt components.\n\n\nYou must \ninstall the compiler tools\n to \nsupport native compiling to build the project this tutorial creates.  \n\n\nYou have a board with BLE radio that is supported by Mynewt. We will use an nRF52 Dev board in this tutorial.\n\n\nCable to establish a serial USB connection between the board and the laptop\n\n\n\n\n\n\nCreate a project\n\n\nUse the Newt tool to create a new project directory containing a skeletal Mynewt framework. Change into the newly created directory.\n\n\n$ newt new myapp1\nDownloading project skeleton from apache/incubator-
 mynewt-blinky...\nInstalling skeleton in myapp1...\nProject myapp1 successfully created.\n$ cd myapp1\n\n$ newt install -v \napache-mynewt-core\nDownloading repository description for apache-mynewt-core... success!\n...\napache-mynewt-core successfully installed version 0.7.9-none\n\n\n\n\n\n\n\nCreate targets\n\n\nYou will create two targets - one for the bootloader, the other for the application.\n\n\n$ newt target create myble\nTarget targets/myble successfully created\n$ newt target create nrf52_boot\nTarget targets/myble successfully created\n$ newt target show\ntargets/my_blinky_sim\n    app=apps/blinky\n    bsp=@apache-mynewt-core/hw/bsp/native\n    build_profile=debug\ntargets/myble\ntargets/nrf52_boot\n\n\n\n\n\n\n\nDefine the targets further. Note that you are using the example app \nbletiny\n 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). \n\n\n$ newt target set myble 
 bsp=@apache-mynewt-core/hw/bsp/nrf52pdk\nTarget targets/myble successfully set target.bsp to @apache-mynewt-core/hw/bsp/nrf52pdk\n$ newt target set myble app=@apache-mynewt-core/apps/bletiny\nTarget targets/myble successfully set target.app to @apache-mynewt-core/apps/bletiny\n$ newt target set myble build_profile=optimized\nTarget targets/myble successfully set target.build_profile to optimized\n$ newt target set myble cflags=-DSTATS_NAME_ENABLE\nTarget targets/myble successfully set pkg.cflags to DSTATS_NAME_ENABLE\n\n\n\n\n\nUse the same \nnewt target set\n command to set the following definition for the bootloader target.\n\n\ntargets/nrf52_boot\n    app=@apache-mynewt-core/apps/boot\n    bsp=@apache-mynewt-core/hw/bsp/nrf52pdk\n    build_profile=optimized\n\n\n\n\n\nYou should have the following targets by the end of this step.\n\n\n$ newt target show\ntargets/my_blinky_sim\n    app=apps/blinky\n    bsp=@apache-mynewt-core/hw/bsp/native\n    build_profile=debug\ntargets/myble\n
     app=@apache-mynewt-core/apps/bletiny\n    bsp=@apache-mynewt-core/hw/bsp/nrf52pdk\n    build_profile=optimized\n    cflags=-DSTATS_NAME_ENABLE \ntargets/nrf52_boot\n    app=@apache-mynewt-core/apps/boot\n    bsp=@apache-mynewt-core/hw/bsp/nrf52pdk\n    build_profile=optimized\n\n\n\n\n\nBuild targets\n\n\nThen build the two targets.\n\n\n$ newt build nrf52_boot\n\nsnip\n\nApp successfully built: ./bin/nrf52_boot/apps/boot/boot.elf\n$ newt build myble\nCompiling hci_common.c\nCompiling util.c\nArchiving nimble.a\nCompiling os.c\n\nsnip\n\n\n\n\n\n\n\n\nCreate the app image\n\n\nGenerate a signed application image for the \nmyble\n target. The version number is arbitrary.\n\n\n$ newt create-image myble 1.0.0\nApp image succesfully generated: ./bin/makerbeacon/apps/bletiny/bletiny.img\nBuild manifest: ./bin/makerbeacon/apps/bletiny/manifest.json\n\n\n\n\n\n\n\nLoad the image\n\n\nMake sure the USB connector is in place and the power LED on the board is lit. Use the Power ON/OFF swi
 tch to reset the board after loading the image.\n\n\n$ newt load myble\n\n\n\n\n\n\n\nEstablish serial connection\n\n\nYou will now look for some BLE related stats over a serial connection and see the radio is actually working. The picture below shows a serial connector set up.\n\n\n\n\n\n\nYou may use any terminal emulation program to communicate with the board. This tutorial shows a Minicom set up. You will have to find out what the usbserial port number is on your laptop, of course.\n\n\n$ minicom -D /dev/tty.usbserial-AJ03HAQQ\n\n\n\n\n\n\n\nWhen the Minicom screen comes up, type in \n?\n\n\nWelcome to minicom 2.7\n\nOPTIONS: \nCompiled on Nov 24 2015, 16:14:21.\nPort /dev/tty.usbserial-AJ03HAQQ, 09:57:17\n\nPress Meta-Z for help on special keys\n\n\n?\n\n4828455:log     echo    ?       tasks   mempools        date \n4828457:stat    b \n\n\n\n\n\n\n\nTry the \nstat\n command. \n\n\nstat\n\n4973017:Must specify a statistic name to dump, possible names are:\n4973021:        stat\n
 4973022:        ble_l2cap\n4973024:        ble_att\n4973026:        ble_gap\n4973027:        ble_gattc\n4973029:        ble_gatts\n4973031:        ble_hs\n4973032:        ble_ll_conn\n4973034:        ble_ll\n\n\n\n\n\n\n\nTry specifying a BLE related stat, for example \nble_ll\n. You should see some HCI (Host Controller Interface) command counts. \n\n\nstat ble_ll\n\n4986297:hci_cmds: 5\n4986297:hci_cmd_errs: 0\n4986299:hci_events_sent: 5\n4986301:bad_ll_state: 0\n4986303:bad_acl_hdr: 0\n4986306:rx_adv_pdu_crc_ok: 0\n4986308:rx_adv_pdu_crc_err: 0\n4986311:rx_adv_bytes_crc_ok: 0\n4986314:rx_adv_bytes_crc_err: 0\n4986317:rx_data_pdu_crc_ok: 0\n4986319:rx_data_pdu_crc_err: 0\n4986322:rx_data_bytes_crc_ok: 0\n\nsnip\n\n\n\n\n\n\n\n\nFor a more exciting output, try scanning your surroundings for BLE adverstisements. The HCI command shown below specifies a scan duration in ms, sets discovery mode to general (as opposed to limited), the filter to no-whitelist, and type of scan to passive. 
 You should see some scan data flying by!\n\n\nb scan dur=10000 disc=gen filt=no_wl type=passive\n\n\n5301227:[ts=5301227ssb, mod=4 level=1] host_hci_cmd_send: ogf=0x08 ocf=0x0b len=7\n5301233:[ts=5301233ssb, mod=4 level=1] Command Complete: cmd_pkts=1 ogf=0x8 ocf=0xb status=0\n5301241:[ts=5301241ssb, mod=4 level=1] host_hci_cmd_send: ogf=0x08 ocf=0x0c len=2\n5301248:[ts=5301248ssb, mod=4 level=1] Command Complete: cmd_pkts=1 ogf=0x8 ocf=0xc status=0\nGAP procedure initiated: discovery; disc_mode=2 filter_policyLE advertising report. len=38 num=1 evtype=3 addr9\n5301270:[ts=5301270ssb, mod=4 level=1] 02 01 06 03 03 aa fe 12 \n5301276:[ts=5301276ssb, mod=4 level=1] 16 aa fe 10 f6 02 67 2e \n5301281:[ts=5301281ssb, mod=4 level=1] 63 6f 2f 62 65 61 63 6f \n5301287:[ts=5301287ssb, mod=4 level=1] 6e 73 \n5301291:[ts=5301291ssb, mod=64 level=2] received advertisement; event_type=3 addr_type=1 addr=0xa0:0x0d:0xec:0:\n5301316:[ts=5301316ssb, mod=64 level=2]     flags=0x06\n5301321:[ts=530132
 1ssb, mod=64 level=2]     uuids16(complete)=0xfeaa \n5301327:[ts=5301327ssb, mod=64 level=2]     svc_data_uuid16=\n\nsnip", 
+            "text": "Check stats on a BLE device\n\n\n\n\nThis 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.\n\n\n\n\nPre-Requisites\n\n\n\n\nEnsure you have installed \nnewt\n and that the \nnewt command is in your system path. \n\n\nYou must have Internet connectivity to fetch remote Mynewt components.\n\n\nYou must \ninstall the compiler tools\n to \nsupport native compiling to build the project this tutorial creates.  \n\n\nYou must install the \nSegger JLINK package\n to load your project on the board.\n\n\nYou have a board with BLE radio that is supported by Mynewt. We will use an nRF52 Dev board in this tutorial.\n\n\nCable to establish a serial USB connection between the board and the laptop\n\n\n\n\n\n\nCreate a project\n\n\nUse the Newt tool to create a new project directory containing a skeletal Mynewt framework. Change into the newly created 
 directory.\n\n\n$ newt new myapp1\nDownloading project skeleton from apache/incubator-mynewt-blinky...\nInstalling skeleton in myapp1...\nProject myapp1 successfully created.\n$ cd myapp1\n\n$ newt install -v \napache-mynewt-core\nDownloading repository description for apache-mynewt-core... success!\n...\napache-mynewt-core successfully installed version 0.7.9-none\n\n\n\n\n\n\n\nCreate targets\n\n\nYou will create two targets - one for the bootloader, the other for the application.\n\n\n$ newt target create myble\nTarget targets/myble successfully created\n$ newt target create nrf52_boot\nTarget targets/myble successfully created\n$ newt target show\ntargets/my_blinky_sim\n    app=apps/blinky\n    bsp=@apache-mynewt-core/hw/bsp/native\n    build_profile=debug\ntargets/myble\ntargets/nrf52_boot\n\n\n\n\n\n\n\nDefine the targets further. Note that you are using the example app \nbletiny\n 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. Look on the top of your board, if you see PCA100040, use the nrf52dk version, otherwide use the nrf52pdk version). \n\n\n$ newt target set myble bsp=@apache-mynewt-core/hw/bsp/nrf52pdk\nTarget targets/myble successfully set target.bsp to @apache-mynewt-core/hw/bsp/nrf52pdk\n$ newt target set myble app=@apache-mynewt-core/apps/bletiny\nTarget targets/myble successfully set target.app to @apache-mynewt-core/apps/bletiny\n$ newt target set myble build_profile=optimized\nTarget targets/myble successfully set target.build_profile to optimized\n$ newt target set myble cflags=-DSTATS_NAME_ENABLE\nTarget targets/myble successfully set pkg.cflags to DSTATS_NAME_ENABLE\n\n\n\n\n\nUse the same \nnewt target set\n 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..\n\n\ntargets/nrf52_boot\n    app=@apache-mynewt-core/apps/b
 oot\n    bsp=@apache-mynewt-core/hw/bsp/nrf52pdk\n    build_profile=optimized\n\n\n\n\n\nYou should have the following targets by the end of this step.\n\n\n$ newt target show\ntargets/my_blinky_sim\n    app=apps/blinky\n    bsp=@apache-mynewt-core/hw/bsp/native\n    build_profile=debug\ntargets/myble\n    app=@apache-mynewt-core/apps/bletiny\n    bsp=@apache-mynewt-core/hw/bsp/nrf52pdk\n    build_profile=optimized\n    cflags=-DSTATS_NAME_ENABLE \ntargets/nrf52_boot\n    app=@apache-mynewt-core/apps/boot\n    bsp=@apache-mynewt-core/hw/bsp/nrf52pdk\n    build_profile=optimized\n\n\n\n\n\nBuild targets\n\n\nThen build the two targets.\n\n\n$ newt build nrf52_boot\n\nsnip\n\nApp successfully built: ./bin/nrf52_boot/apps/boot/boot.elf\n$ newt build myble\nCompiling hci_common.c\nCompiling util.c\nArchiving nimble.a\nCompiling os.c\n\nsnip\n\n\n\n\n\n\n\n\nCreate the app image\n\n\nGenerate a signed application image for the \nmyble\n target. The version number is arbitrary.\n\n\n$ new
 t create-image myble 1.0.0\nApp image succesfully generated: ./bin/makerbeacon/apps/bletiny/bletiny.img\nBuild manifest: ./bin/makerbeacon/apps/bletiny/manifest.json\n\n\n\n\n\n\n\nLoad the image\n\n\nMake 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.\n\n\n$ newt load nrf52_boot\n$ newt load myble\n\n\n\n\n\n\n\nEstablish serial connection\n\n\nYou will now look for some BLE related stats over a serial connection and see the radio is actually working. The picture below shows a serial connector set up. Pin PA.08 is RX and pin PA.06 is TX. Make sure TX from the NRF52 goes to RX on your Serial board, and that RX on the NRF52 goes to TX on your Serial Board.\n\n\n\n\n\n\nYou may use any terminal emulation program to communicate with the board. This tutorial shows a Minicom set up. You will have to find out what the usbserial port number is on your laptop, of course.\n\n\n$ minicom -D /dev
 /tty.usbserial-AJ03HAQQ\n\n\n\n\n\n\n\nWhen the Minicom screen comes up, type in \n?\n\n\nWelcome to minicom 2.7\n\nOPTIONS: \nCompiled on Nov 24 2015, 16:14:21.\nPort /dev/tty.usbserial-AJ03HAQQ, 09:57:17\n\nPress Meta-Z for help on special keys\n\n\n?\n\n4828455:log     echo    ?       tasks   mempools        date \n4828457:stat    b \n\n\n\n\n\n\n\nTry the \nstat\n command. \n\n\nstat\n\n4973017:Must specify a statistic name to dump, possible names are:\n4973021:        stat\n4973022:        ble_l2cap\n4973024:        ble_att\n4973026:        ble_gap\n4973027:        ble_gattc\n4973029:        ble_gatts\n4973031:        ble_hs\n4973032:        ble_ll_conn\n4973034:        ble_ll\n\n\n\n\n\n\n\nTry specifying a BLE related stat, for example \nble_ll\n. You should see some HCI (Host Controller Interface) command counts. \n\n\nstat ble_ll\n\n4986297:hci_cmds: 5\n4986297:hci_cmd_errs: 0\n4986299:hci_events_sent: 5\n4986301:bad_ll_state: 0\n4986303:bad_acl_hdr: 0\n4986306:rx_adv_pdu_c
 rc_ok: 0\n4986308:rx_adv_pdu_crc_err: 0\n4986311:rx_adv_bytes_crc_ok: 0\n4986314:rx_adv_bytes_crc_err: 0\n4986317:rx_data_pdu_crc_ok: 0\n4986319:rx_data_pdu_crc_err: 0\n4986322:rx_data_bytes_crc_ok: 0\n\nsnip\n\n\n\n\n\n\n\n\nFor a more exciting output, try scanning your surroundings for BLE adverstisements. The HCI command shown below specifies a scan duration in ms, sets discovery mode to general (as opposed to limited), the filter to no-whitelist, and type of scan to passive. You should see some scan data flying by!\n\n\nb scan dur=10000 disc=gen filt=no_wl type=passive\n\n\n5301227:[ts=5301227ssb, mod=4 level=1] host_hci_cmd_send: ogf=0x08 ocf=0x0b len=7\n5301233:[ts=5301233ssb, mod=4 level=1] Command Complete: cmd_pkts=1 ogf=0x8 ocf=0xb status=0\n5301241:[ts=5301241ssb, mod=4 level=1] host_hci_cmd_send: ogf=0x08 ocf=0x0c len=2\n5301248:[ts=5301248ssb, mod=4 level=1] Command Complete: cmd_pkts=1 ogf=0x8 ocf=0xc status=0\nGAP procedure initiated: discovery; disc_mode=2 filter_pol
 icyLE advertising report. len=38 num=1 evtype=3 addr9\n5301270:[ts=5301270ssb, mod=4 level=1] 02 01 06 03 03 aa fe 12 \n5301276:[ts=5301276ssb, mod=4 level=1] 16 aa fe 10 f6 02 67 2e \n5301281:[ts=5301281ssb, mod=4 level=1] 63 6f 2f 62 65 61 63 6f \n5301287:[ts=5301287ssb, mod=4 level=1] 6e 73 \n5301291:[ts=5301291ssb, mod=64 level=2] received advertisement; event_type=3 addr_type=1 addr=0xa0:0x0d:0xec:0:\n5301316:[ts=5301316ssb, mod=64 level=2]     flags=0x06\n5301321:[ts=5301321ssb, mod=64 level=2]     uuids16(complete)=0xfeaa \n5301327:[ts=5301327ssb, mod=64 level=2]     svc_data_uuid16=\n\nsnip\n\n\n\n\n\n\n\n\nIf you're still not seeing any output from the device, try running the debugger and see if you are seeing the program execute properly. \n\n\n\n\n$ newt debug myble\nDebugging ./bin/myble/apps/bletiny/bletiny.elf\nGNU gdb (GNU Tools for ARM Embedded Processors) 7.6.0.20140731-cvs\nCopyright (C) 2013 Free Software Foundation, Inc.\n\nLicense GPLv3+: GNU GPL version 3 or la
 ter \nhttp://gnu.org/licenses/gpl.html\n\nThis is free software: you are free to change and redistribute it.\nThere is NO WARRANTY, to the extent permitted by law.  Type \nshow copying\n\nand \nshow warranty\n for details.\nThis GDB was configured as \n--host=x86_64-apple-darwin10 --target=arm-none-eabi\n.\nFor bug reporting instructions, please see:\n\nhttp://www.gnu.org/software/gdb/bugs/\n...\nReading symbols from ./bin/myble/apps/bletiny/bletiny.elf...done.\n0x00002f08 in ?? ()\n(gdb) monitor reset\nResetting target\n(gdb) c\nContinuing.\n^C\nProgram received signal SIGTRAP, Trace/breakpoint trap.\nos_tick_idle (ticks=1000) at hal_os_tick.c:117\n117     if (ticks \n 0) {\n(gdb) p g_os_time\n$1 = 37991\n(gdb) c\nContinuing.\n^C\nProgram received signal SIGTRAP, Trace/breakpoint trap.\nos_tick_idle (ticks=1000) at hal_os_tick.c:117\n117     if (ticks \n 0) {\n(gdb) p g_os_time\n$2 = 51888\n(gdb) c\nContinuing.\n\n\n\n\n\n\n\nYou 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"
         }, 
         {
@@ -1222,7 +1222,7 @@
         }, 
         {
             "location": "/os/tutorials/bletiny_project/#pre-requisites", 
-            "text": "Ensure you have installed  newt  and that the \nnewt command is in your system path.   You must have Internet connectivity to fetch remote Mynewt components.  You must  install the compiler tools  to \nsupport native compiling to build the project this tutorial creates.    You have a board with BLE radio that is supported by Mynewt. We will use a

<TRUNCATED>