How to copy peripheral_uart example for custom service

I have been experimenting with the peripheral_uart example and it looks like it is a good basis for the program I need to write. The problem I face is that the uart services I need to implement require a change of UUIDs. Unfortunately, I don't see a way of being able to copy the peripheral_uart example and have custom service UUIDs. The file "nus.h" is in the SDK and so should not be changed, plus, making a copy into my local project directory and having "main.c" use it is not sufficient because other parts of the NUS source in the SDK make reference to the SDK "nus.h".

So, is it possible to get a copy of the example into my project space that would only use my updated "nus.h".

  • Hi,

    You can make copies of nus.c and nus.h inside your project. Copy the complete files and add them to, for example, src. Then rename the files and change the code to replace every instance of "nus" with the name of your custom service instead, for example:

    int bt_nus_init(struct bt_nus_cb *callbacks) -> int bt_custom_us_init(struct bt_custom_us_cb *callbacks)

    The only thing you should not rename is the UART device in main.c:

    static const struct device *uart = DEVICE_DT_GET(DT_CHOSEN(nordic_nus_uart));

    If you want more information about adding custom services, one of my colleagues has made a tutorial here: https://github.com/edvinand/custom_ncs_ble_service_sample.

    Best regards,

    Marte

  • Hello ) thank you for your advice. I tried to do that but, not being familiar with CMake I am having trouble getting my project to use the copied files. If you had a link to a guide for adjusting the source files used in a project, I would much appreciate it.

    Also, thank you for the link to the tutorial, I will be checking that out later.

    Sid 

  • Hi Sid,

    You need to add the source file with target_sources() and the directory where the include file is located with zephyr_library_include_directories(). So if you, for example, named the copied NUS files custom_service.h and custom_service.c, and they are located in src, your CMakeLists.txt can look something like this:

    cmake_minimum_required(VERSION 3.20.0)
    
    find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
    project(NONE)
    
    # NORDIC SDK APP START
    target_sources(app PRIVATE
      src/main.c
      src/custom_service.c
    )
    
    # Include UART ASYNC API adapter
    target_sources_ifdef(CONFIG_BT_NUS_UART_ASYNC_ADAPTER app PRIVATE
      src/uart_async_adapter.c
    )
    
    # Preinitialization related to Thingy:53 DFU
    target_sources_ifdef(CONFIG_BOARD_THINGY53_NRF5340_CPUAPP app PRIVATE
      boards/thingy53.c
    )
    target_sources_ifdef(CONFIG_BOARD_THINGY53_NRF5340_CPUAPP_NS app PRIVATE
      boards/thingy53.c
    )
    
    # NORDIC SDK APP END
    
    zephyr_library_include_directories(src)
    

    Here I used the CMakeLists.txt from peripheral_uart, and the changes I made are on lines 9 and 27.

    In addition, you need to include your header file in main.c:

    #include "custom_service.h"

    Best regards,

    Marte

  • Thank you. 

    I copied, nus.c and nus_client.c to my src folder and added them to the CMakeLists.txt file. Before making further changes I tried to build the project and I get a number of errors.

    #
    # Copyright (c) 2018 Nordic Semiconductor
    #
    # SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
    #
    cmake_minimum_required(VERSION 3.20.0)
    
    find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
    project(NONE)
    
    # NORDIC SDK APP START
    target_sources(app PRIVATE
      src/main.c
      src/nus.c
      src/nus_client.c
    )
    
    # Include UART ASYNC API adapter
    target_sources_ifdef(CONFIG_BT_NUS_UART_ASYNC_ADAPTER app PRIVATE
      src/uart_async_adapter.c
    )
    
    # Preinitialization related to Thingy:53 DFU
    target_sources_ifdef(CONFIG_BOARD_THINGY53_NRF5340_CPUAPP app PRIVATE
      boards/thingy53.c
    )
    target_sources_ifdef(CONFIG_BOARD_THINGY53_NRF5340_CPUAPP_NS app PRIVATE
      boards/thingy53.c
    )
    
    # NORDIC SDK APP END
    
    zephyr_library_include_directories(., src)

    /src/nus_client.c.obj -c ../src/nus_client.c
    In file included from C:\ncs\v2.2.0\zephyr\include\zephyr\sys\util_macro.h:34,
                     from C:\ncs\v2.2.0\zephyr\include\zephyr\sys\util.h:17,
                     from C:\ncs\v2.2.0\zephyr\include\zephyr\bluetooth\bluetooth.h:22,
                     from C:\ncs\v2.2.0\zephyr\include\zephyr\bluetooth\conn.h:22,
                     from d:\DataRoot\Projects\Equla\Nordic_Apps\peripheral_uart\src\nus_client.c:7:
    d:\DataRoot\Projects\Equla\Nordic_Apps\peripheral_uart\src\nus_client.c:20:28: error: 'CONFIG_BT_NUS_CLIENT_LOG_LEVEL' undeclared here (not in a function); did you mean 'CONFIG_BT_NUS_LOG_LEVEL'?
       20 | LOG_MODULE_REGISTER(nus_c, CONFIG_BT_NUS_CLIENT_LOG_LEVEL);
          |                            ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    C:\ncs\v2.2.0\zephyr\include\zephyr\sys\util_internal.h:72:26: note: in definition of macro '__DEBRACKET'
       72 | #define __DEBRACKET(...) __VA_ARGS__
          |                          ^~~~~~~~~~~
    C:\ncs\v2.2.0\zephyr\include\zephyr\sys\util_internal.h:64:9: note: in expansion of macro '__GET_ARG2_DEBRACKET'
       64 |         __GET_ARG2_DEBRACKET(one_or_two_args _if_code, _else_code)
          |         ^~~~~~~~~~~~~~~~~~~~
    C:\ncs\v2.2.0\zephyr\include\zephyr\logging\log_core.h:85:9: note: in expansion of macro '__COND_CODE'
       85 |         __COND_CODE(_LOG_ZZZZ##_eval_level, _iftrue, _iffalse)
          |         ^~~~~~~~~~~
    C:\ncs\v2.2.0\zephyr\include\zephyr\logging\log_core.h:82:9: note: in expansion of macro 'Z_LOG_EVAL1'
       82 |         Z_LOG_EVAL1(_eval_level, _iftrue, _iffalse)
          |         ^~~~~~~~~~~
    C:\ncs\v2.2.0\zephyr\include\zephyr\logging\log.h:291:9: note: in expansion of macro 'Z_LOG_EVAL'
      291 |         Z_LOG_EVAL(LOG_LEVEL, \
          |         ^~~~~~~~~~
    C:\ncs\v2.2.0\zephyr\include\zephyr\sys\util_macro.h:308:27: note: in expansion of macro 'Z_GET_ARG_2'
      308 | #define GET_ARG_N(N, ...) Z_GET_ARG_##N(__VA_ARGS__)
          |                           ^~~~~~~~~~
    C:\ncs\v2.2.0\zephyr\include\zephyr\logging\log.h:293:20: note: in expansion of macro 'GET_ARG_N'
      293 |                   (GET_ARG_N(2, __VA_ARGS__, CONFIG_LOG_DEFAULT_LEVEL)))
          |                    ^~~~~~~~~
    C:\ncs\v2.2.0\zephyr\include\zephyr\logging\log.h:418:41: note: in expansion of macro '_LOG_LEVEL_RESOLVE'
      418 |                                         _LOG_LEVEL_RESOLVE(__VA_ARGS__)
          |                                         ^~~~~~~~~~~~~~~~~~
    C:\ncs\v2.2.0\zephyr\include\zephyr\logging\log.h:370:9: note: in expansion of macro 'LOG_MODULE_DECLARE'
      370 |         LOG_MODULE_DECLARE(__VA_ARGS__)
          |         ^~~~~~~~~~~~~~~~~~
    d:\DataRoot\Projects\Equla\Nordic_Apps\peripheral_uart\src\nus_client.c:20:1: note: in expansion of macro 'LOG_MODULE_REGISTER'
       20 | LOG_MODULE_REGISTER(nus_c, CONFIG_BT_NUS_CLIENT_LOG_LEVEL);
          | ^~~~~~~~~~~~~~~~~~~

  • Hi,

    SidPrice said:
    Before making further changes I tried to build the project and I get a number of errors.

    The errors are from the logging module. You can remove the log level of the registration, and the error will disappear. Change the line where you register the log module from this:

    LOG_MODULE_REGISTER(bt_nus, CONFIG_BT_NUS_LOG_LEVEL);

    To this:

    LOG_MODULE_REGISTER(bt_nus);

    Make sure to copy nus.h into your project and to change the names of the files and functions to ensure your project does not use the incorrect NUS files.

    Best regards,

    Marte

Related