This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

How to use the NRF5_SDK?

I'm using the nordic SDK since version 8 (now version 16). For various reasons I always tried to not use the SDK and just programmed against the soft device API and programmed the peripherals directly (which is thanks to the sound design of the peripheral quite easy). But things changes, the SDK probably became more powerful and now I would like to give it a new try. (I also want to avoid problems like this https://devzone.nordicsemi.com/f/nordic-q-a/48161/unexpected-sd_app_evt_wait-returning)

My first task seems to be easy: just add an UART to the application. According to the UART module documentation, I have to define APP_UART_ENABLED to 1 and APP_UART_DRIVER_INSTANCE to 0. Now, when I compile nRF5_SDK/components/libraries/uart/app_uart.c, I get complains from the compiler that types like nrf_uarte_baudrate_t, nrf_uarte_error_mask_t or nrf_uarte_hwfc_t are missing in function declarations from nrf_drv_uart.h:122.

In file included from /Users/todi/bloomlife/sensor-blp/src/nordic/nRF5_SDK/components/libraries/uart/app_uart.c:43:
/Users/todi/bloomlife/sensor-blp/src/nordic/nRF5_SDK/integration/nrfx/legacy/nrf_drv_uart.h:122:13: error: unknown type name 'nrf_uarte_baudrate_t'
  122 |     typedef nrf_uarte_baudrate_t        nrf_uart_baudrate_t;
      |             ^~~~~~~~~~~~~~~~~~~~
/Users/todi/bloomlife/sensor-blp/src/nordic/nRF5_SDK/integration/nrfx/legacy/nrf_drv_uart.h:127:13: error: unknown type name 'nrf_uarte_error_mask_t'
  127 |     typedef nrf_uarte_error_mask_t      nrf_uart_error_mask_t;
      |             ^~~~~~~~~~~~~~~~~~~~~~

Searching for the error message in the devzone, I found https://devzone.nordicsemi.com/f/nordic-q-a/48424/unknown-type-name-error-in-nrf_drv_uart-h/192615#192615 but none of the mentioned defines (UART_EASY_DMA_SUPPORT, UART_LEGACY_SUPPORT or UART_ENABLED) changed the result of the compilation.

Searching for the missing types, reveals the types are defined in modules/nrfx/hal/nrf_uarte.h searching through the whole sdk. I found no include of that file, that would have been conditional, which could have given me a clue as to what would have to be defined to make app_uart.c compile.

Ok, so lets see if I have to enable other modules, not mentioned in the documentation of App Uart. app_uart_init() is basically just a tiny wrapper around nrf_drv_uart_init(). Where is that nrf_drv_uart_init defined? in integration/nrfx/legacy/nrf_drv_uart.c. The path name "legacy" makes me think, that this might be somehow deprecated. nrf_drv_uart.c. makes heavy use of NRF_DRV_UART_WITH_UARTE, which is nowhere defined, maybe this is used as a configuration. Searching for  NRF_DRV_UART_WITH_UARTE in the documentation, yields https://infocenter.nordicsemi.com/topic/sdk_nrf5_v16.0.0/hardware_driver_uart.html but without mentioning NRF_DRV_UART_WITH_UARTE. Ok, so lets just assume, that I need the UART hardware driver. I probably want to use the UARTE (with E for EasyDMA). According to the documentation of the UART hardware driver, I have to look into the documentation the UARTE HAL and to the UART driver legacy layer.

The UARTE HAL has no documented configurations. But the UART driver legacy layer has a set of configurations documented! Ok I found, that I probably have add the following definitions to my configuration:

#define UART_ENABLED 1
#define UART_EASY_DMA_SUPPORT 1
#define UART_LEGACY_SUPPORT 1
#define UART0_ENABLED 1

But unfortunately this still does not change the compiler error messages. The documentation of the UART hardware driver itself sets also UART0_USE_EASY_DMA. But that changes nothing.

Ok, let look into the configuration of an example like ble_app_uart and search for the term UART: 188 matches. Ok, the legacy layer is enabled: UART_ENABLED 1  and the configuration of the legacy layer seems quite similar to mine. But NRFX_UARTE_ENABLED is also set to 1. I suspect this to be the not legacy layer. When I set that define and NRFX_UARTE0_ENABLED app_uart.c finally compiles without errors.

app_uart.c used nrf_drv_uart_init(), which is defined in integration/nrfx/legacy/nrf_drv_uart.c so I probably have to add that to my project. But now, when compiling this file, I get compiler error, complaining about the missing definition of ret_code_t. Sounds very basic. After a few hours of work I give up. This is my final configuration, which does not work:

// UART - Configuration
#define APP_UART_ENABLED 1
#define APP_UART_DRIVER_INSTANCE 0
#define NRFX_UARTE_ENABLED 1
#define NRFX_UARTE0_ENABLED 1
#define UART_ENABLED 1
#define UART_EASY_DMA_SUPPORT 1
#define UART0_USE_EASY_DMA true
#define UART_LEGACY_SUPPORT 1
#define UART0_ENABLED 1
#define UART_ENABLED 1
#define UART_EASY_DMA_SUPPORT 1
#define UART_LEGACY_SUPPORT 1

I have some questions:

- How am I'm supposed to figure out, how to set configurations, if they are not documented? Where are the dependencies which app_uart probably has, documented?

- Am I'm supposed to use the UART module, or is it somehow deprecated?

best regards,

Torsten

Parents
  • By copying the sdk_config.h from the example, I could at least figure out that I have also have to copy the list of ~130 include paths to use the UART. Now I try again to use the original SDKs sdk_config.h and try to move the UART relevant configurations into out app_config.h. That's my current app_config.h:

    #pragma once
    
    // UART - Configuration
    #define APP_UART_ENABLED 1
    #define APP_UART_DRIVER_INSTANCE 0
    #define NRFX_UARTE_ENABLED 1
    #define NRFX_UARTE0_ENABLED 0
    #define NRFX_UART_ENABLED 1
    #define NRFX_UART0_ENABLED 0
    #define UART_ENABLED 1
    #define UART_EASY_DMA_SUPPORT 1
    #define UART_LEGACY_SUPPORT 1
    #define UART0_ENABLED 1
    
    // enable the softdevice
    #define NRF_SDH_ENABLED 1
    #define NRF_SDH_SOC_ENABLED 1
    #define NRF_SDH_BLE_ENABLED 1
    

    Now, this leads to a double definition of UARTE0_UART0_IRQHandler. According to the sources of nrfx_uart.c, the interrupt handler should have been compiled only when NRFX_UART0_ENABLED is set to 1. In my settings, it was set to 0. By compiling nrfx_uart.c with preprocessor output enabled, I found that NRFX_UART0_ENABLED will be undefined and redefined to 1 in integration/nrfx/legacy/apply_old_config.h. But only if UART_ENABLED is set, which is set and it's also set in the SDK example, when UART0_ENABLED is set to 1 and UART_LEGACY_SUPPORT is set to 1. Which they are in my configuration and the configuration of the example.

    So maybe the definition in UARTE0_UART0_IRQHandler is correct and not the one in nrfx_uarte.c? Same play there, ISR should be compiled only if NRFX_UARTE0_ENABLED is set to 1, which is not done by my configuration, but by apply_old_config.h because UART_ENABLED, UART0_ENABLED and UART_EASY_DMA_SUPPORT are set to 1 (like in the SDK example).

    So maybe integration/nrfx/legacy/apply_old_config.h should not have been compiled? Which is only include once in the overall sdk from a file called integration/nrfx/nrfx_glue.h. That include is unconditional, so maybe integration/nrfx/nrfx_glue.h was not supposed to be included? Well it's unconditional included by nrfx.h. The documentation in nrfx_glue.h states "This file contains macros that should be implemented according to
    * the needs of the host environment into which @em nrfx is integrated.". Maybe the example has its own nrfx_glue.h? No, there are two versions of that file and the example uses the one under integration/nrfx/nrfx_glue.h. But maybe my project is using the version of nrfx_glue.h under modules/nrfx/templates? No, my project uses also the same header as the example is doing.

    So, I don't have a clue, why my project does not link, maybe I can figure out, why the example doesn't have the same problem...

    To my surprise, both IRQ handlers in nrfx_uart.c and nrfx_uarte.c are compiled and both object files linked into the example binary. So maybe the nrfx_uarte_0_irq_handler and nrfx_uart_0_irq_handler macros are resolved differently in the example!? I compile the SDK example with preprocessor output enabled to see how they are solved: in nrfx_uart.c the IRQ handler name nrfx_uart_0_irq_handler resolves to nrfx_uart_0_irq_handler. nrfx_uarte_0_irq_handler resolves to nrfx_uarte_0_irq_handler. So none of the macros in the example are resolved to the IRQ name UARTE0_UART0_IRQHandler.

    Ok, why is nrfx_uart_0_irq_handler and nrfx_uarte_0_irq_handler handler defined to UARTE0_UART0_IRQHandler in my project? According to the preprocessor output of nrfx_uart.c, they are defined to UARTE0_UART0_IRQHandler in nrfx_irqs_nrf52832,h because, both NRFX_PRS_ENABLED and NRFX_PRS_BOX_4_ENABLED are set. In the example, NRFX_PRS_ENABLED is set to 1 and NRFX_PRS_BOX_4_ENABLED is set to 1 too. In the default sdk version, this both defines are not even mentioned. But I will apply that difference to my app_config.h. I don't know why this works, but it works now. In case someone else want to integrate an UART in his BLE project, here is the required configuration (app_config.h):

    #pragma once
    
    // UART - Configuration
    #define APP_UART_ENABLED 1
    #define APP_UART_DRIVER_INSTANCE 0
    #define NRFX_UARTE_ENABLED 1
    #define NRFX_UARTE0_ENABLED 0
    #define NRFX_UART_ENABLED 1
    #define NRFX_UART0_ENABLED 0
    #define UART_ENABLED 1
    #define UART_EASY_DMA_SUPPORT 1
    #define UART_LEGACY_SUPPORT 1
    #define UART0_ENABLED 1
    #define APP_FIFO_ENABLED 1
    
    // enable the softdevice
    #define NRF_SDH_ENABLED 1
    #define NRF_SDH_SOC_ENABLED 1
    #define NRF_SDH_BLE_ENABLED 1
    
    // nrfx_prs - Peripheral Resource Sharing module
    #define NRFX_PRS_ENABLED 1
    // Enables box 4 in the module.
    #define NRFX_PRS_BOX_4_ENABLED 1

    Still some question remain:

    - Why box 4? (what is a box?)

    - Why is all that LEGACY stuff required?

    - How am I'm supposed to find all this required setting?

    best regards,

    Torsten

Reply
  • By copying the sdk_config.h from the example, I could at least figure out that I have also have to copy the list of ~130 include paths to use the UART. Now I try again to use the original SDKs sdk_config.h and try to move the UART relevant configurations into out app_config.h. That's my current app_config.h:

    #pragma once
    
    // UART - Configuration
    #define APP_UART_ENABLED 1
    #define APP_UART_DRIVER_INSTANCE 0
    #define NRFX_UARTE_ENABLED 1
    #define NRFX_UARTE0_ENABLED 0
    #define NRFX_UART_ENABLED 1
    #define NRFX_UART0_ENABLED 0
    #define UART_ENABLED 1
    #define UART_EASY_DMA_SUPPORT 1
    #define UART_LEGACY_SUPPORT 1
    #define UART0_ENABLED 1
    
    // enable the softdevice
    #define NRF_SDH_ENABLED 1
    #define NRF_SDH_SOC_ENABLED 1
    #define NRF_SDH_BLE_ENABLED 1
    

    Now, this leads to a double definition of UARTE0_UART0_IRQHandler. According to the sources of nrfx_uart.c, the interrupt handler should have been compiled only when NRFX_UART0_ENABLED is set to 1. In my settings, it was set to 0. By compiling nrfx_uart.c with preprocessor output enabled, I found that NRFX_UART0_ENABLED will be undefined and redefined to 1 in integration/nrfx/legacy/apply_old_config.h. But only if UART_ENABLED is set, which is set and it's also set in the SDK example, when UART0_ENABLED is set to 1 and UART_LEGACY_SUPPORT is set to 1. Which they are in my configuration and the configuration of the example.

    So maybe the definition in UARTE0_UART0_IRQHandler is correct and not the one in nrfx_uarte.c? Same play there, ISR should be compiled only if NRFX_UARTE0_ENABLED is set to 1, which is not done by my configuration, but by apply_old_config.h because UART_ENABLED, UART0_ENABLED and UART_EASY_DMA_SUPPORT are set to 1 (like in the SDK example).

    So maybe integration/nrfx/legacy/apply_old_config.h should not have been compiled? Which is only include once in the overall sdk from a file called integration/nrfx/nrfx_glue.h. That include is unconditional, so maybe integration/nrfx/nrfx_glue.h was not supposed to be included? Well it's unconditional included by nrfx.h. The documentation in nrfx_glue.h states "This file contains macros that should be implemented according to
    * the needs of the host environment into which @em nrfx is integrated.". Maybe the example has its own nrfx_glue.h? No, there are two versions of that file and the example uses the one under integration/nrfx/nrfx_glue.h. But maybe my project is using the version of nrfx_glue.h under modules/nrfx/templates? No, my project uses also the same header as the example is doing.

    So, I don't have a clue, why my project does not link, maybe I can figure out, why the example doesn't have the same problem...

    To my surprise, both IRQ handlers in nrfx_uart.c and nrfx_uarte.c are compiled and both object files linked into the example binary. So maybe the nrfx_uarte_0_irq_handler and nrfx_uart_0_irq_handler macros are resolved differently in the example!? I compile the SDK example with preprocessor output enabled to see how they are solved: in nrfx_uart.c the IRQ handler name nrfx_uart_0_irq_handler resolves to nrfx_uart_0_irq_handler. nrfx_uarte_0_irq_handler resolves to nrfx_uarte_0_irq_handler. So none of the macros in the example are resolved to the IRQ name UARTE0_UART0_IRQHandler.

    Ok, why is nrfx_uart_0_irq_handler and nrfx_uarte_0_irq_handler handler defined to UARTE0_UART0_IRQHandler in my project? According to the preprocessor output of nrfx_uart.c, they are defined to UARTE0_UART0_IRQHandler in nrfx_irqs_nrf52832,h because, both NRFX_PRS_ENABLED and NRFX_PRS_BOX_4_ENABLED are set. In the example, NRFX_PRS_ENABLED is set to 1 and NRFX_PRS_BOX_4_ENABLED is set to 1 too. In the default sdk version, this both defines are not even mentioned. But I will apply that difference to my app_config.h. I don't know why this works, but it works now. In case someone else want to integrate an UART in his BLE project, here is the required configuration (app_config.h):

    #pragma once
    
    // UART - Configuration
    #define APP_UART_ENABLED 1
    #define APP_UART_DRIVER_INSTANCE 0
    #define NRFX_UARTE_ENABLED 1
    #define NRFX_UARTE0_ENABLED 0
    #define NRFX_UART_ENABLED 1
    #define NRFX_UART0_ENABLED 0
    #define UART_ENABLED 1
    #define UART_EASY_DMA_SUPPORT 1
    #define UART_LEGACY_SUPPORT 1
    #define UART0_ENABLED 1
    #define APP_FIFO_ENABLED 1
    
    // enable the softdevice
    #define NRF_SDH_ENABLED 1
    #define NRF_SDH_SOC_ENABLED 1
    #define NRF_SDH_BLE_ENABLED 1
    
    // nrfx_prs - Peripheral Resource Sharing module
    #define NRFX_PRS_ENABLED 1
    // Enables box 4 in the module.
    #define NRFX_PRS_BOX_4_ENABLED 1

    Still some question remain:

    - Why box 4? (what is a box?)

    - Why is all that LEGACY stuff required?

    - How am I'm supposed to find all this required setting?

    best regards,

    Torsten

Children
Related