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

DMA for UART with Zephyr on nRF9160

Hello,

I would like to use DMA on UART1 on the nRF9160.  Can you provide an example for setting up the UART with DMA for Zephyr?  I can't find any documentation or direction.

Thanks,

JL

  • Hi JL,

    The UART on nRF9160 uses DMA. See nRF9160 Objective Product Specification. An example can be found here.

    Hope this helps!

    Kind regards,
    Øyvind

  • Hello,

    Yes, I have implemented the UART in this fashion, however I don't see the benefits of DMA capability! I am getting an interrupt per byte.  Upon further investigation I see that the RXD.MAXCNT is hard coded to 1 in the NRFX UART driver code.  Additionally, I can't find where the API will give me the ability to set the RXD.PTR register.  I see that it gets set during  initialization by a start-up routine.

    So, my question is, do I have API access to update RXD.MAXCNT and RXD.PTR so that I can get the full benefit of DMA?

    Thanks,

    JL

  • Hello,

    I was just informed that we released an API / test case to use UARTE on the nRF9160. Have a look here.

    gonzalezjl said:
    So, my question is, do I have API access to update RXD.MAXCNT and RXD.PTR so that I can get the full benefit of DMA?

     From nrfx_uarte.h:

    /**
     * @brief Function for sending data over UARTE.
     *
     * If an event handler is provided in nrfx_uarte_init() call, this function
     * returns immediately and the handler is called when the transfer is done.
     * Otherwise, the transfer is performed in blocking mode, that is this function
     * returns when the transfer is finished. Blocking mode is not using interrupt
     * so there is no context switching inside the function.
     *
     * @note Peripherals using EasyDMA (including UARTE) require the transfer buffers
     *       to be placed in the Data RAM region. If this condition is not met,
     *       this function will fail with the error code NRFX_ERROR_INVALID_ADDR.
     *
     * @param[in] p_instance Pointer to the driver instance structure.
     * @param[in] p_data     Pointer to data.
     * @param[in] length     Number of bytes to send. Maximum possible length is
     *                       dependent on the used SoC (see the MAXCNT register
     *                       description in the Product Specification). The driver
     *                       checks it with assertion.
     *
     * @retval NRFX_SUCCESS            Initialization was successful.
     * @retval NRFX_ERROR_BUSY         Driver is already transferring.
     * @retval NRFX_ERROR_FORBIDDEN    The transfer was aborted from a different context
     *                                 (blocking mode only).
     * @retval NRFX_ERROR_INVALID_ADDR p_data does not point to RAM buffer.
     */
    nrfx_err_t nrfx_uarte_tx(nrfx_uarte_t const * p_instance,
                             uint8_t const *      p_data,
                             size_t               length);

    Kind regards,
    Øyvind

  • This is good, however. I can't get it to work.  I have followed all  instructions in the example, have disabled interrupts for UARTE (which I don't like since I also want to use the Shell and it forces interrupts on) and have disabled the MPU.  When I hit the function;

    uart_callback_set(usb_uart_dev, usb_uart_callback, &dummy);

    I get the following;

    ***** HARD FAULT *****

      Fault escalation (see below)

    ***** BUS FAULT *****

      Precise data bus error

      BFAR Address: 0x50008120

    ***** Hardware exception *****

    Current thread ID = 0x20020354

    Faulting instruction address = 0x1

    Fatal fault in ISR! Spinning...

    At a loss as to why this is happening.  Any help would be great.

  • Please remember that the nRF9160 is a far more advanced device which uses the Zephyr OS to handle communication, drivers, peripherals etc. How did you disable the interrupts? In this case, it seems that you are getting the hard fault due to disabling the interrupts as it hard faults on a callback, part of the ISR. From the Zephyr glossary:

    Interrupt Service Routine (ISR) Also known as an interrupt handler, an ISR is a callback function whose execution is triggered by a hardware interrupt (or software interrupt instructions) and is used to handle high-priority conditions that require interrupting the current code executing on the processor.

    Another possible reason for the hard fault is disabling the MPU. How did you disable the MPU?

    Kind regards,
    Øyvind

Related