| Developing an Application for an Onboard Sensor |
| ----------------------------------------------- |
| |
| This tutorial shows you how to develop a simple application for an |
| onboard sensor. The Mynewt sensor framework enables you to easily and |
| quickly develop Mynewt sensor applications. We assume that you have |
| completed the :doc:`Enabling an Off-Board Sensor in an Existing Application |
| Tutorial <sensor_nrf52_bno055>` and are familiar with the sensor |
| framework and sensor shell command. |
| |
| This tutorial shows you how to: |
| |
| - Develop an application for the Nordic Thingy LIS2DH12 accelerometer |
| onboard sensor with the sensor framework ``sensor`` shell command |
| enabled to view sensor data. |
| - Extend the application to use the sensor framework API to read the |
| sensor data and output the data to the Mynewt console. |
| |
| .. contents:: |
| :local: |
| :depth: 2 |
| |
| Prerequisites |
| ~~~~~~~~~~~~~ |
| |
| - Meet the prerequisites listed in the :doc:`Sensor Tutorials |
| Overview <sensors_framework>` |
| - Have a Nordic Thingy. |
| - `Segger J-Link Debug |
| Probe <https://www.segger.com/jlink-debug-probes.html>`__. |
| - `J-Link 9 pin Cortex-M |
| Adapter <https://www.segger.com/jlink-adapters.html#CM_9pin>`__ 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 <https://www.segger.com/jlink-software.html>`__. |
| - Complete the :doc:`Enabling an Off-Board Sensor in an Existing Application |
| Tutorial <sensor_nrf52_bno055>` |
| |
| Developing a Sensor Enabled Application with Shell Support |
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| |
| We first develop a simple application with the LIS2DH12 onboard sensor |
| on the Nordic Thingy and the ``sensor`` shell command enabled. |
| |
| Step 1: Creating a New App Package |
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ |
| |
| |
| We name the new app package ``my_sensor_app``. From your project base |
| directory, run the ``newt pkg new`` command to create a new app package. |
| This tutorial uses ~/dev/myproj for the project. |
| |
| .. code-block:: console |
| |
| $ cd ~/dev/myproj |
| $ newt pkg new -t app apps/my_sensor_app |
| Download package template for package type app. |
| Package successfuly installed into ~/dev/myproj/apps/my_sensor_app |
| |
| The newt tool creates a skeleton ``my_sensor_app`` package directory in |
| the ``~/dev/myproj/apps/`` directory. Go to the ``my_sensor_app`` |
| directory to update the package ``pkg.yml`` and source files. |
| |
| .. code-block:: console |
| |
| |
| $ cd apps/my_sensor_app |
| |
| Step 2: Adding the Package Dependencies |
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ |
| |
| |
| The my\_sensor\_app package requires the sensor framework, |
| ``hw/sensor``, package as a package dependency. Note that the BSP |
| creates the sensor devices for the onboard sensors, so the |
| ``hw/sensor/creator`` package that creates off-board sensor is not |
| needed. |
| |
| Add the highlighted line to the ``pkg.yml`` file to add the |
| ``hw/sensor`` package as package dependency: |
| |
| .. code-block:: console |
| :emphasize-lines: 6 |
| |
| pkg.deps: |
| - "@apache-mynewt-core/kernel/os" |
| - "@apache-mynewt-core/sys/console/full" |
| - "@apache-mynewt-core/sys/log/full" |
| - "@apache-mynewt-core/sys/stats/full" |
| - "@apache-mynewt-core/hw/sensor" |
| |
| |
| |
| Step 3: Using the Skeleton main.c File |
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ |
| |
| |
| The newt tool creates a skeleton main.c file in the |
| ``my_sensor_app/src`` directory. The skeleton ``main()`` code shown is |
| all you need to build an application that only uses the ``sensor`` shell |
| command to read sensor data. You do not need to make any changes to the |
| file. The sensor framework implements the ``sensor`` shell command and |
| the shell package processes shell command events from the OS default |
| event queue. |
| |
| .. code-block:: c |
| |
| |
| int |
| main(int argc, char **argv) |
| { |
| /* Perform some extra setup if we're running in the simulator. */ |
| #ifdef ARCH_sim |
| mcu_sim_parse_args(argc, argv); |
| #endif |
| |
| /* Initialize all packages. */ |
| sysinit(); |
| |
| /* As the last thing, process events from default event queue. */ |
| while (1) { |
| os_eventq_run(os_eventq_dflt_get()); |
| } |
| |
| return 0; |
| } |
| |
| Step 4: Creating the Target for the my\_sensor\_app Application |
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ |
| |
| |
| You create a target for the my\_sensor\_app to run on the Nordic Thingy. |
| The following syscfg settings must be set: |
| |
| - ``I2C_0=1`` : Enables the I2C interface 0 for the nRF52 Thingy BSP |
| HAL setting to communicate with the onboard sensor. |
| - ``LIS2DH12_ONB=1``: Enables the lis2dh12 onboard sensor support in |
| the nRF52 Thingy BSP. |
| |
| A BSP with onboard sensors defines a syscfg setting for each onboard |
| sensor it supports and uses the naming convention |
| ``<SENSORNAME>_ONB``. The ``<SENSORNAME>_ONB`` setting specifies |
| whether the sensor named SENSORNAME is enabled. The setting is |
| disabled by default. The BSP includes the sensor device driver |
| package ``hw/drivers/sensors/<sensorname>`` and creates and |
| configures the onboard sensor named SENSORNAME when the |
| ``<SENSORNAME>_ONB`` setting is enabled by the application. |
| |
| - ``SHELL_TASK=1``: Enables the shell task for the shell command |
| support. Note that the ``hw/sensor`` package enables the |
| ``SENSOR_CLI`` setting by default. |
| - ``SENSOR_OIC=0``: Disables the OIC sensor server support in the |
| sensor framework. |
| - ``CONSOLE_RTT=1``: Enables console communication via the SEGGER RTT. |
| The nRF52 Thingy does not have a UART so we use the RTT for the |
| console. |
| - ``CONSOLE_UART=0``: Disables the console communication via a UART. |
| |
| **Note:** The lis2dh12 sensor device driver package, |
| ``/hw/driver/sensors/lis2dh12``, currently does not support a shell |
| command to view information on the device. |
| |
| 1. Run the following newt commands to create the target and set the |
| application and BSP. |
| |
| .. code-block:: console |
| |
| |
| $ newt target create thingy_my_sensor |
| Target targets/thingy_my_sensor successfully created |
| $ newt target set thingy_my_sensor bsp=@apache-mynewt-core/hw/bsp/nrf52-thingy |
| Target targets/thingy_my_sensor successfully set target.bsp to @apache-mynewt-core/hw/bsp/nrf52-thingy |
| $ newt target set thingy_my_sensor app=apps/my_sensor_app |
| Target targets/thingy_my_sensor successfully set target.app to apps/my_sensor_app |
| $ newt target set thingy_my_sensor build_profile=debug |
| Target targets/thingy_my_sensor successfully set target.build_profile to debug |
| |
| 2. Run the following ``newt target set`` command to set the syscfg |
| settings: |
| |
| .. code-block:: console |
| |
| |
| $ newt target set thingy_my_sensor syscfg=I2C_0=1:LIS2DH12_ONB=1:SHELL_TASK=1:CONSOLE_RTT=1:CONSOLE_UART=0:SENSOR_OIC=0 |
| Target targets/thingy_my_sensor successfully set target.syscfg to I2C_0=1:LIS2DH12_ONB=1:SHELL_TASK=1:CONSOLE_RTT=1:CONSOLE_UART=0:SENSOR_OIC=0 |
| |
| Step 5: Creating and Building the Bootloader Target |
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ |
| |
| |
| Create a target for the bootloader for the nRF52 Thingy. We name the |
| target ``thingy_boot``. |
| |
| 1. Run the following ``newt target`` commands to create the target: |
| |
| .. code-block:: console |
| |
| |
| $ newt target create thingy_boot |
| Target targets/thingy_boot successfully created |
| $ newt target set thingy_boot bsp=@apache-mynewt-core/hw/bsp/nrf52-thingy |
| Target targets/thingy_boot successfully set target.bsp to @apache-mynewt-core/hw/bsp/nrf52-thingy |
| $ newt target set thingy_boot app=@mcuboot/boot/mynewt |
| Target targets/thingy_boot successfully set target.app to @mcuboot/boot/mynewt |
| $ newt target set thingy_boot build_profile=optimized |
| Target targets/thingy_boot successfully set target.build_profile to optimized |
| |
| 2. Run the ``newt build`` command to build the bootloader target: |
| |
| .. code-block:: console |
| |
| |
| $ newt build thingy_boot |
| Building target targets/thingy_boot |
| |
| ... |
| |
| Archiving thingy_boot-sysinit-app.a |
| Archiving util_mem.a |
| Linking ~/dev/myproj/bin/targets/thingy_boot/app/boot/mynewt/mynewt.elf |
| Target successfully built: targets/thingy_boot |
| |
| Step 6: Connecting the Thingy to your Computer |
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ |
| |
| Perform the following steps to connect the Thingy to your computer: |
| |
| 1. Move the power switch to the left to power ON the Thingy: |
| |
| |Thingy| |
| |
| 2. Connect the debug probe to the JTAG port on the board using the |
| Jlink 9-pin adapter and cable, and connect the probe to your computer. |
| |
| |J-Link debug probe to Thingy| |
| |
| .. raw:: html |
| |
| <p> |
| |
| Step 7: Loading the Image and Connecting to the Console via RTT |
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ |
| |
| |
| To run the application, you need to load the bootloader on to the |
| device, load the application image, and start a GDB debug process for |
| RTT to attach to. |
| |
| |
| 1. Run the ``newt load`` command to load the bootloader: |
| |
| .. code-block:: console |
| |
| $ newt load thingy_boot |
| Loading bootloader |
| |
| |
| 2. Run the ``newt run`` command to build and create an image for the |
| my\_sensor\_app, load the image, and start a GDB process to debug the |
| application: |
| |
| .. code-block:: console |
| |
| $ newt run thingy_my_sensor 1.0.0 |
| Assembling repos/apache-mynewt-core/hw/bsp/nrf52-thingy/src/arch/cortex_m4/gcc_startup_nrf52_split.s |
| Compiling repos/apache-mynewt-core/hw/cmsis-core/src/cmsis_nvic.c |
| Assembling repos/apache-mynewt-core/hw/bsp/nrf52-thingy/src/arch/cortex_m4/gcc_startup_nrf52.s |
| Compiling repos/apache-mynewt-core/encoding/base64/src/hex.c |
| Compiling apps/my_sensor_app/src/main.c |
| |
| ... |
| |
| Archiving thingy_my_sensor-sysinit-app.a |
| Archiving time_datetime.a |
| Archiving util_cbmem.a |
| Archiving util_crc.a |
| Archiving util_mem.a |
| Archiving util_parse.a |
| Linking ~/dev/myproj/bin/targets/thingy_my_sensor/app/apps/my_sensor_app/my_sensor_app.elf |
| App image succesfully generated: ~/dev/myproj/bin/targets/thingy_my_sensor/app/apps/my_sensor_app/my_sensor_app.img |
| Loading app image into slot 1 |
| [~/dev/myproj/repos/apache-mynewt-core/hw/bsp/nrf52-thingy/nrf52-thingy_debug.sh ~/dev/myproj/repos/apache-mynewt-core/hw/bsp/nrf52-thingy ~/dev/myproj/bin/targets/thingy_my_sensor/app/apps/my_sensor_app/my_sensor_app] |
| Debugging ~/dev/myproj/bin/targets/thingy_my_sensor/app/apps/my_sensor_app/my_sensor_app.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/thingy_my_sensor/app/apps/my_sensor_app/my_sensor_app.elf...done. |
| os_tick_idle (ticks=24) |
| at repos/apache-mynewt-core/hw/mcu/nordic/nrf52xxx/src/hal_os_tick.c:204 |
| 204 if (ticks > 0) { |
| Resetting target |
| 0x000000dc in ?? () |
| (gdb) |
| |
| 3. Enter ``c <return>`` in the (gdb) prompt to continue. |
| |
| 4. Run the following telnet command to connect to the Mynewt console |
| via RTT and enter <return> to get the shell prompt after you are |
| connected. |
| |
| .. code-block:: console |
| |
| $ telnet localhost 19021 |
| Trying ::1... |
| telnet: connect to address ::1: Connection refused |
| Trying 127.0.0.1... |
| Connected to localhost. |
| Escape character is '^]'. |
| SEGGER J-Link V6.14h - Real time terminal output |
| SEGGER J-Link ARM V10.0, SN=600000268 |
| Process: JLinkGDBServer |
| |
| 011468 compat> |
| |
| Step 8: Viewing the list of Sensors and Sensor Data |
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ |
| |
| 1. Enter ``sensor list`` to see the sensors that are registered with |
| the sensor manager. You should see the ``lis2dh12_0`` sensor. This |
| sensor is only configured for the accelerometer (0x1). |
| |
| .. code-block:: console |
| |
| |
| 011468 compat> sensor list |
| sensor list |
| 029706 sensor dev = lis2dh12_0, configured type = 0x1 |
| 029707 compat> |
| |
| 2. Enter the ``sensor read`` command to read some data samples from the |
| accelerometer: |
| |
| .. code-block:: console |
| |
| |
| 029707 compat> sensor read lis2dh12_0 0x1 -n 5 |
| sensor read lis2dh12_0 0x1 -n 5 |
| 042537 ts: [ secs: 331 usecs: 102682 cputime: 331436945 ] |
| 042537 x = 9.806650176 y = 58.839900992 z = -9894.910156 |
| 042537 ts: [ secs: 331 usecs: 104832 cputime: 331439095 ] |
| 042537 x = 19.613300352 y = 98.066497804 z = -9924.330078 |
| 042537 ts: [ secs: 331 usecs: 106988 cputime: 331441251 ] |
| 042537 x = 9.806650176 y = 49.033248902 z = -9904.716796 |
| 042538 ts: [ secs: 331 usecs: 109137 cputime: 331443400 ] |
| 042538 x = 9.806650176 y = 29.419950496 z = -9904.716796 |
| 042538 ts: [ secs: 331 usecs: 111288 cputime: 331445551 ] |
| 042538 x = 58.839900992 y = 0.000000000 z = -9816.457031 |
| 042538 compat> |
| |
| Extending the Application to Use the Sensor API to Read Sensor Data |
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ |
| |
| |
| As this tutorial demonstrates so far, the Mynewt sensor framework |
| enables you to easily and quickly develop an application with a sensor |
| and view the sensor data from the ``sensor`` shell command. We now |
| extend the application to use the sensor API to read the sensor data. |
| |
| There are two sensor functions that you can use to read data from a |
| sensor device: |
| |
| - ``sensor_register_listener()``: This function allows you to register |
| a listener for a sensor device. You specify a bit mask of the types |
| of sensor data to listen for and a callback to call when data is read |
| from the sensor device. The listener callback is called whenever the |
| ``sensor_read()`` function reads data for a sensor type from a sensor |
| device that the listener is listening for. |
| |
| The sensor framework supports polling of sensor devices. For a sensor |
| device that has a polling rate configured, the sensor framework |
| poller reads sensor data for all the configured sensor types from the |
| sensor device at each polling interval and calls the registered |
| listener callbacks with the sensor data. |
| |
| - ``sensor_read()``: This function reads sensor data from a sensor |
| device and calls the specified user callback to receive the sensor |
| data. You specify a bit mask of the types of sensor data to read from |
| a sensor device and a callback. This callback is called for each |
| sensor type you specify to read. |
| |
| We first extend the application to a register a sensor listener to |
| demonstrate how to use the sensor framework polling support. We then |
| extend the application to use the ``sensor_read()`` function instead of |
| a listener. An application may not need to poll sensors. For example, an |
| application that processes remote requests for sensor data might only |
| read the sensor data when it receives a request. |
| |
| Step 1: Modifying main.c to Add a Sensor Listener |
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ |
| |
| |
| Add the following code to the ``my_sensor_app/src/main.c`` file: |
| |
| 1. Add the highlighted include files: |
| |
| .. code-block:: c |
| :emphasize-lines: 4, 5, 6, 7 |
| |
| #include "sysinit/sysinit.h" |
| #include "os/os.h" |
| |
| #include <defs/error.h> |
| #include <sensor/sensor.h> |
| #include <sensor/accel.h> |
| #include <console/console.h> |
| |
| 2. Add the ``struct sensor *my_sensor``. This is the handle for the |
| sensor that the sensor API uses to perform operations on the sensor. We |
| set this variable when we lookup the sensor. |
| |
| .. code-block:: c |
| |
| static struct sensor *my_sensor; |
| |
| 3. Declare and initialize a sensor listener. You specify a bit mask for |
| the sensor types to listen for, the callback function, and an opaque |
| argument to pass to the callback. You initialize the type to |
| SENSOR\_TYPE\_ACCELEROMETER, the listener callback to the |
| ``read_accelerometer()`` function, and the callback opaque argument to |
| the LISTENER\_CB value. |
| |
| **Note**: We define LISTENER\_CB and READ\_CB values because we also use |
| the ``read_accelerometer()`` function as the callback for the |
| ``sensor_read()`` function later in the tutorial. The LISTENER\_CB or |
| the READ\_CB value is passed to the ``read_accelerometer()`` function to |
| indicate whether it is invoked as a listener or a ``sensor_read()`` |
| callback. |
| |
| .. code-block:: c |
| |
| #define LISTENER_CB 1 |
| #define READ_CB 2 |
| |
| static int read_accelerometer(struct sensor* sensor, void *arg, void *databuf, sensor_type_t type); |
| |
| static struct sensor_listener listener = { |
| .sl_sensor_type = SENSOR_TYPE_ACCELEROMETER, |
| .sl_func = read_accelerometer, |
| .sl_arg = (void *)LISTENER_CB, |
| }; |
| |
| 4. Add the code for the ``read_accelerometer()`` function. The sensor |
| data is stored in the ``databuf`` and ``type`` specifies the type of |
| sensor data. |
| |
| .. code-block:: c |
| |
| static int |
| read_accelerometer(struct sensor* sensor, void *arg, void *databuf, sensor_type_t type) |
| { |
| |
| char tmpstr[13]; |
| struct sensor_accel_data *sad; |
| |
| if (!databuf) { |
| return SYS_EINVAL; |
| |
| } |
| sad = (struct sensor_accel_data *)databuf; |
| |
| if (!sad->sad_x_is_valid || |
| !sad->sad_y_is_valid || |
| !sad->sad_z_is_valid) { |
| |
| return SYS_EINVAL; |
| } |
| |
| console_printf("%s: [ secs: %ld usecs: %d cputime: %u ]\n", |
| ((int)arg == LISTENER_CB) ? "LISTENER_CB" : "READ_CB", |
| (long int)sensor->s_sts.st_ostv.tv_sec, |
| (int)sensor->s_sts.st_ostv.tv_usec, |
| (unsigned int)sensor->s_sts.st_cputime); |
| |
| console_printf("x = %s ", sensor_ftostr(sad->sad_x, tmpstr, 13)); |
| console_printf("y = %s ", sensor_ftostr(sad->sad_y, tmpstr, 13)); |
| console_printf("z = %s\n\n", sensor_ftostr(sad->sad_z, tmpstr, 13)); |
| return 0; |
| } |
| |
| 5. Set the poll rate for the sensor to two seconds. The |
| ``sensor_set_poll_rate_ms()`` function sets the poll rate for a named |
| sensor. |
| |
| **Note:** You set the poll rate for a sensor programmatically and must |
| set the poll rate to a non zero value in order for the sensor manager to |
| poll the sensor. You may set a different poll rate for each sensor. The |
| sensor framework also defines a ``SENSOR_MGR_WAKEUP_RATE`` syscfg |
| setting that specifies the default rate that the sensor manager polls. |
| The sensor manager uses the poll rate for a sesnor if a sensor is |
| configured to poll more frequently than the ``SENSOR_MGR_WAKEUP_RATE`` |
| setting value. |
| |
| .. code-block:: c |
| :emphasize-lines: 1, 2, 8, 15, 16 |
| |
| #define MY_SENSOR_DEVICE "lis2dh12_0" |
| #define MY_SENSOR_POLL_TIME 2000 |
| |
| |
| int |
| main(int argc, char \*\*argv) |
| { |
| int rc; |
| |
| ... |
| |
| /* Initialize all packages. */ |
| sysinit(); |
| |
| rc = sensor_set_poll_rate_ms(MY_SENSOR_DEVICE, MY_SENSOR_POLL_TIME); |
| assert(rc == 0); |
| |
| |
| /* As the last thing, process events from default event queue. */ |
| while (1) { |
| os_eventq_run(os_eventq_dflt_get()); |
| } |
| |
| return 0; |
| |
| } |
| |
| 6. Look up the sensor by name to get the handle for the sensor and |
| register a listener for the sensor. |
| |
| .. code-block:: c |
| :emphasize-lines: 10, 11, 12, 13 |
| |
| int |
| main(int argc, char **argv) |
| { |
| |
| ... |
| |
| rc = sensor_set_poll_rate_ms(MY_SENSOR_DEVICE, MY_SENSOR_POLL_TIME); |
| assert(rc == 0); |
| |
| my_sensor = sensor_mgr_find_next_bydevname(MY_SENSOR_DEVICE, NULL); |
| assert(my_sensor != NULL); |
| rc = sensor_register_listener(my_sensor, &listener); |
| assert(rc == 0); |
| |
| /* As the last thing, process events from default event queue. */ |
| while (1) { |
| os_eventq_run(os_eventq_dflt_get()); |
| } |
| |
| return 0; |
| |
| } |
| |
| |
| Step 2: Rebuilding the Application and Connecting to Console |
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ |
| |
| |
| 1. Run the ``newt run`` command to rebuild the application, create a |
| new image, load the image, and start a GDB process: |
| |
| .. code-block:: console |
| |
| |
| $ newt run thingy_my_sensor 2.0.0 |
| Compiling apps/my_sensor_app/src/main.c |
| Archiving apps_my_sensor_app.a |
| Linking ~/dev/myproj/bin/targets/thingy_my_sensor/app/apps/my_sensor_app/my_sensor_app.elf |
| App image succesfully generated: ~/dev/myproj/bin/targets/thingy_my_sensor/app/apps/my_sensor_app/my_sensor_app.img |
| Loading app image into slot 1 |
| [~/dev/myproj/repos/apache-mynewt-core/hw/bsp/nrf52-thingy/nrf52-thingy_debug.sh ~/dev/myproj/repos/apache-mynewt-core/hw/bsp/nrf52-thingy ~/dev/myproj/bin/targets/thingy_my_sensor/app/apps/my_sensor_app/my_sensor_app] |
| Debugging ~/dev/myproj/bin/targets/thingy_my_sensor/app/apps/my_sensor_app/my_sensor_app.elf |
| GNU gdb (GNU Tools for ARM Embedded Processors) 7.8.0.20150604-cvs |
| |
| ... |
| |
| Reading symbols from ~/dev/myproj/bin/targets/thingy_my_sensor/app/apps/my_sensor_app/my_sensor_app.elf...done. |
| os_tick_idle (ticks=12) |
| at repos/apache-mynewt-core/hw/mcu/nordic/nrf52xxx/src/hal_os_tick.c:204 |
| 204 if (ticks > 0) { |
| Resetting target |
| 0x000000dc in ?? () |
| (gdb) c |
| Continuing. |
| |
| 2. Connect to the console via RTT: |
| |
| .. code-block:: console |
| |
| $ telnet localhost 19021 |
| |
| Connected to localhost. |
| Escape character is '^]'. |
| SEGGER J-Link V6.14h - Real time terminal output |
| J-Link OB-SAM3U128-V2-NordicSemi compiled Mar 2 2017 12:22:13 V1.0, SN=682562963 |
| Process: JLinkGDBServer |
| 000003 LISTENER_CB: [ secs: 0 usecs: 23407 cputime: 331783 ] |
| 000003 x = 117.67980192 y = -19.61330035 z = -9885.103515 |
| |
| 000259 LISTENER_CB: [ secs: 2 usecs: 21190 cputime: 2327645 ] |
| 000259 x = 117.67980192 y = -9.806650176 z = -9914.523437 |
| |
| 000515 LISTENER_CB: [ secs: 4 usecs: 17032 cputime: 4323487 ] |
| 000515 x = 78.453201280 y = 0.000000000 z = -9924.330078 |
| |
| 000771 LISTENER_CB: [ secs: 6 usecs: 13131 cputime: 6319586 ] |
| 000771 x = 117.67980192 y = -19.61330035 z = -9914.523437 |
| |
| 001027 LISTENER_CB: [ secs: 8 usecs: 8810 cputime: 8315265 ] |
| 001027 x = 127.48645020 y = 0.000000000 z = -9924.330078 |
| |
| 001283 LISTENER_CB: [ secs: 10 usecs: 4964 cputime: 10311419 ] |
| 001283 x = 58.839900992 y = -9.806650176 z = -9885.103515 |
| |
| You should see the accelerometer sensor data output from the listener |
| callback. |
| |
| Step 3: Modifying main.c to Use sensor\_read() Instead of a Listener |
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ |
| |
| Lets extend the application to use the ``sensor_read()`` function |
| instead of a listener. We setup an OS callout to call the |
| ``sensor_read()`` function for illustration purposes. A real application |
| will most likely read the sensor data when it gets a request or some |
| other event. |
| |
| 1. Add an OS callout and initialize an OS timer to fire every 5 |
| seconds. The timer callback calls the ``sensor_read()`` function to read |
| the sensor data. The ``read_accelerometer()`` callback is called when |
| the sensor data is read. The READ\_CB value is passed to the |
| ``read_accelerometer()`` function and indicates that the callback is |
| from the ``sensor_read()`` function and not from the listener. |
| |
| .. code-block:: c |
| |
| /* |
| * Event callback function for timer events. The callback reads the sensor data |
| */ |
| |
| #define READ_SENSOR_INTERVAL (5 * OS_TICKS_PER_SEC) |
| |
| static struct os_callout sensor_callout; |
| |
| static void |
| timer_ev_cb(struct os_event *ev) |
| { |
| |
| |
| assert(ev != NULL); |
| |
| /* |
| * Read the accelerometer sensor. Pass the READ_CB value for the callback opaque |
| * arg to indicate that it is the sensor_read() callback. |
| */ |
| sensor_read(my_sensor, SENSOR_TYPE_ACCELEROMETER, read_accelerometer, |
| (void *)READ_CB, OS_TIMEOUT_NEVER); |
| os_callout_reset(&sensor_callout, READ_SENSOR_INTERVAL); |
| return; |
| } |
| |
| |
| static void |
| init_timer(void) |
| { |
| /* |
| * Initialize the callout for a timer event. |
| */ |
| os_callout_init(&sensor_callout, os_eventq_dflt_get(), |
| timer_ev_cb, NULL); |
| |
| os_callout_reset(&sensor_callout, READ_SENSOR_INTERVAL); |
| return; |
| } |
| |
| 2. Remove the listener registration and call the ``init_timer()`` |
| function in ``main()``. You can delete the |
| ``sensor_register_listener()`` function call, but we call the |
| ``sensor_unregister_listener()`` function to illustrate how to use this |
| function. |
| |
| .. code-block:: c |
| :emphasize-lines: 10, 11, 13 |
| |
| int |
| main(int argc, char **argv) |
| { |
| ... |
| |
| assert(my_sensor != NULL); |
| rc = sensor_register_listener(my_sensor, &listener); |
| assert(rc == 0); |
| |
| rc = sensor_unregister_listener(my_sensor, &listener); |
| assert(rc == 0); |
| |
| init_timer(); |
| |
| /* As the last thing, process events from default event queue. */ |
| while (1) { |
| os_eventq_run(os_eventq_dflt_get()); |
| } |
| |
| return 0; |
| } |
| |
| Step 4: Rebuilding the Application and Connecting to Console |
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ |
| |
| 1. Run the ``newt run`` command to rebuild the application, create an new |
| image, and start a GDB process: |
| |
| .. code-block:: console |
| |
| $ newt run thingy_my_sensor 3.0.0 |
| Compiling apps/my_sensor_app/src/main.c |
| Archiving apps_my_sensor_app.a |
| Linking ~/dev/myproj/bin/targets/thingy_my_sensor/app/apps/my_sensor_app/my_sensor_app.elf |
| App image succesfully generated: ~/dev/myproj/bin/targets/thingy_my_sensor/app/apps/my_sensor_app/my_sensor_app.img |
| Loading app image into slot 1 |
| [~/dev/myproj/repos/apache-mynewt-core/hw/bsp/nrf52-thingy/nrf52-thingy_debug.sh ~/dev/myproj/repos/apache-mynewt-core/hw/bsp/nrf52-thingy ~/dev/myproj/bin/targets/thingy_my_sensor/app/apps/my_sensor_app/my_sensor_app] |
| Debugging ~/dev/myproj/bin/targets/thingy_my_sensor/app/apps/my_sensor_app/my_sensor_app.elf |
| GNU gdb (GNU Tools for ARM Embedded Processors) 7.8.0.20150604-cvs |
| |
| ... |
| |
| Reading symbols from ~/dev/myproj/bin/targets/thingy_my_sensor/app/apps/my_sensor_app/my_sensor_app.elf...done. |
| os_tick_idle (ticks=12) |
| at repos/apache-mynewt-core/hw/mcu/nordic/nrf52xxx/src/hal_os_tick.c:204 |
| 204 if (ticks > 0) { |
| Resetting target |
| 0x000000dc in ?? () |
| (gdb) c |
| Continuing. |
| |
| 3. Connect to the console via RTT: |
| |
| .. code-block:: console |
| |
| |
| $ telnet localhost 19021 |
| Trying ::1... |
| telnet: connect to address ::1: Connection refused |
| Trying 127.0.0.1... |
| Connected to localhost. |
| Escape character is '^]'. |
| SEGGER J-Link V6.14h - Real time terminal output |
| J-Link OB-SAM3U128-V2-NordicSemi compiled Mar 2 2017 12:22:13 V1.0, SN=682562963 |
| Process: JLinkGDBServer |
| |
| |
| 000629 compat> READ_CB: [ secs: 5 usecs: 4088 cputime: 5295643 ] |
| 000642 x = 98.066497804 y = 0.000000000 z = -9806.650390 |
| |
| 001282 READ_CB: [ secs: 9 usecs: 992459 cputime: 10284014 ] |
| 001282 x = 117.67980192 y = -39.22660064 z = -9894.910156 |
| |
| 001922 READ_CB: [ secs: 14 usecs: 981159 cputime: 15272714 ] |
| 001922 x = 78.453201280 y = -29.41995049 z = -9885.103515 |
| |
| 002562 READ_CB: [ secs: 19 usecs: 970088 cputime: 20261643 ] |
| 002562 x = 107.87315366 y = -29.41995049 z = -9885.103515 |
| |
| You should see the accelerometer sensor data output from the sensor read |
| data callback. |
| |
| .. |Thingy| image:: ../pics/thingy.jpg |
| .. |J-Link debug probe to Thingy| image:: ../pics/thingy_jlink.jpg |