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

UART usage - I cannot see the light in the SDK

In advance I would like to say I’m sorry for the frustration that this message reflects…Event though I have been using the UART for some time, adding more functionality makes me search documentation for a UART description, and this makes me really frustrated.

I have what I think is a relatively simple need, I want to use UART0 and UART1 on a nRF32840 (both for some RS485 communication).

 

I do not care if it is NRF_DRV, NRFX or APP layer, anything that can be made to work will do!

 

Originally, I thought that selecting between NRF or NRFX was simple; documents suggest that NRF is legacy and I should use the "new" NRFX layer.

So selecting NRFX_UART_ENABLE would be logical and then including nrfx_uart.c driver file.....

But nothing is that simple with this SDK.... there always seems to be a mess of dependencies between configuration macros and files you need to include. and absolutely nothing that documents it (except heavy reading of header files of course ;-). I would love to see. “If you want this layer, tick this in SDK config and include ….”)

Well initial suggestion as above for NRFX just creates a bunch of errors…. so what is the combination needed...

It seems I can choose between using:

1 nrf_drv_uart

2 nrfx_uart

3 nrfx_uarte

4 app_uart

Can anyone suggest settings that will make just one of these options work, it would be highly appreciated and hopefully spare me a lot of testing and experimentation.

What I’m looking for what is a combination of what should be in SDK Config for

NRFX_UARTE section

NRFX_UART section

NRF_DRV (UART_ENABLED) section

APP_UART_ENABLED (+APP_FIFO_ENABLED) section

And any other sections that have dependencies!

I want to be able to call ???_init, send one or more bytes and receive bytes one by one

  • A small story... how to get UART working or not working. (before this one day just fumbling around trying to figure out what to do).

    As UARTE is the only method that seems to support both uarts I start by this
    In the sdk config:
    Enable the following
    NRFX_UARTE_ENABLED
    NRFX_UARTE0_ENABLED
    NRFX_UARTE1_ENABLED
    No other uart related sections enabled

    Include nrfx_uart.c in the build

    With this setup nrfx_uarte_init() is undefined!

    This is related to the check of NRFX_UARTE_ENABLED in nrfx_uarte.c line 43.
    As there is only one include file (nrfx.h) before the check, I walk backwards to see what is missing as NRFX_UARTE_ENABLED is set in the sdk_config.h file.
    It seems that nrfx.h includes nrfx_config.h and this does include sdk_config.h so it should be fine, but....
    There is a single #undef of NRFX_UARTE_ENABLED, but it does not seem to be hit, so i cannot directly see the reason.

    So I contine (trial and error)

    Maybe try do include the driver layer by

    Enable UART_ENABLED in sdk config.

    Ok that worked, at least reduced number of errors, but undefinded nrf_drv_... and nrfx_uart_... functions...

    Conclusiong I have to include both legacy and nrfx layer driver files (nrf_drv_uart.c and nrfx_uart.c) also in the project to remove linker error!

    OK, that was it.... not I can compile and link.

    Running is a different issue, I get a application error when initializing the second UART.

    Seems that there is an internal structure m_cb[] where there is only one instance (m_cb[0]). This seems to come from the definition NRFX_UARTE_ENABLED_COUNT.
    But the code for defining it this seems OK, so why do I see a wrong definition. Include file order, what???
    This could be the same as above where something also was wrong with NRFX_UARTE_ENABLED...

    In the file /nrfx/legacy/apply_old_config.h there is a redefinition of NRFX_UARTE1_ENABLED that seems to be depending on both UART1_ENABLED and UART_EASY_DMA_SUPPORT,
    so I'm trying to figure what this requires!
    Aaaahhh error on my side or.., I did not see the UART1_ENABLED when I earlier enabled UART_ENABLED to make it compiler. Why do I at all have to define these myself as I have already enabled using NRFX_UARTE defines?

    That helped, I am able to compile.

    And both init functions succeed. Now on with the usage!

    Now investigating how to use the nrfx_uarte API functions. Transmitting seems straight forward as using nrfx_uarte_tx() should be fine.
    Receiving seems to require more.
    As most protocols and in many situations, I do not know how many characters I expect to received but would like to process them as they come in.
    I do not mind that a few are buffered up, actually the best would be to process mainly on a "gab" detection and a timer.

    I can call nrfx_uarte_rx() with a single byte buffer but does not seem efficient.

    Investigating further....

  • Hello,

    I understand your frustratsion, as this seems to be quite confusing for a lot of users since we introduced the nrfx drivers. 

    First, let me say that there is no choice between legacy and nrfx drivers in the examples in the SDK. I believe some of the old drivers are still present, but you will see that all the examples use the nrfx drivers. Now, the confusing part is that the sdk_config.h file includes both the NRFX and the legacy defines. The reason for this was to make the examples easier to port (backward compatibility), but it has caused a lot of confusion.

    You are probably not aware of the file apply_old_config.h, but if you open it, you will see how the different defines are being set. Basically, if the legacy defines are defined, they will overwrite the NRFX_... defines from sdk_config.h. You will however see if you follow the definitions for the driver functions that there is a port layer between the legacy names and the nrfx drivers.

    E.g. nrf_drv_uart_init() calls nrfx_uart_init() or nrfx_uarte_init() depending on the NRF_DRV_UART_WITH_UARTE and NRF_DRV_UART_WITH_UART define.

    My recommendation is that you set all the NRF_UART defines and the NRFX_UART defines in sdk_config.h equal to each other, and take a look in apply_old_config.h.

    There is also an example in the SDK15.3.0\examples\peripheral\serial_uartes that uses both UARTs. You can read about it's description here.

    It should also be possible to use the app_uart library, that is used in e.g. the ble_app_uart example, and add another uart. Just set both the legacy and nrfx defines to be the same. If you do this, which I believe that you have tried, what sort of errors do you encounter?

    Best regards,

    Edvin

  • Thank you for the information !

    As you can see from my comments, from investigation I found out about the "feature" that you have to define both new NRFX and legacy layer identical. Why not automaticially define legacy if required.

    If I, as a new user selects to use the NRFX layer as recommended. Why do I the have to include lagacy layer also if it's just wrapping the new layer. That does seem to be the case. My app does not link without legacy layer included. 

    I find NO EXAMPLES using nrfx layer.

    I can find examples using APP layer (uart) and just now I found the example using the nrf_serial library (but seems to be using legacy layer) in the serial and serial_uartes examples.

    Any information on how to receive an unknown number of characters? I see the info about double buffering, but do not really find any detailed information or examples I can use.

  • So I just found the libaray nrf_serial.c but no documentation ;-(

    Previously I used weeks fighting with the serial port to get it to work properly I wonder why I did not see this library earlier. Maybe because I searched for things that used the nrfx_uart functions.

    It seems to have nice features but no description about what it really can do, so I will look into it.

    Now for serial port you have the choice of:

    1 nrf_drv_uart

    2 nrfx_uart

    3 nrfx_uarte

    4 app_uart

    5 nrf_serial

    What are the differences, limitations, features would be really great to have an overview.

    I still do not know what my best choice are, or which ones to avoid because they will not work. I have to use hours and hours experimenting.

  • And to top your list there is also nrf_libuarte, which would be #6...

    The uart/uarte difference is that uart doesn't use DMA, while uarte does.

    As to the nrfx/legacy defines, what I have done is to first set the defines equal. Then once I have verified that the nrfx driver works, I delete the legacy defines from my project's sdk_config. That way I end up with just one set of defines to configure the peripheral.

    I think you've already discovered that #1-3 are lower level drivers, and #4-6 are the choices for a higher level driver.

    What are the differences, limitations, features would be really great to have an overview.

    I still do not know what my best choice are, or which ones to avoid because they will not work.

    I'd like to see such an overview as well. And more documentation. I think nrf_serial and nrf_libuarte are the newest, so my advice would be to check out those. And if you want to go to the lower level then try nrfx_uarte.

Related