This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts
This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

The problem of using UART to communicate between nRF160 and nRF2833 on nRF Connect SDK.

Hello, All,

When using UART on nRF Connect SDK to communicate between nrf9160DK and nRF2833DK, I found that the data length of a packet sent by the UART on both sides is different.

When using nRF9160 to send, a data packet can reach more than 1K; but when using nRF2833 to send, it is found that a data packet can only send about 250 bytes.

WHY?

Are there any restrictions?

Is it restricted by DMA?

Where is the explanation about this part?

The sending function I use is: "uart_tx()".

Even if I change the value of the macro CONFIG_UART_0_NRF_TX_BUFFER_SIZE, it has no effect.

Parents
  • Sorry, I was wrong. What I tested was not nRF52833DK but nRF52840DK, because currently nRF52833 will report an error "Not able to allocate UART receive buffer".

    And why does nRF52833 report this problem while nRF52840 is normal?

  • Hi

    Are you saying the nRF52833 will fail even if it uses exactly the same code and the same project configuration?

    How large is the buffer that the nRF52833 fails to allocate?

    Could you try to increase the CONFIG_HEAP_MEM_POOL_SIZE setting in prj.conf and see if the problem goes away?

    Best regards
    Torbjørn

  • Yes, nRF52840 and nRF52833 use the same project and configuration.

    The following is the relevant configuration:

    in prj.conf

    # LOG.
    CONFIG_LOG=y
    CONFIG_USE_SEGGER_RTT=y
    CONFIG_LOG_BACKEND_RTT=y
    CONFIG_LOG_BACKEND_UART=n
    
    # DK library.
    CONFIG_DK_LIBRARY=y
    
    # UART.
    CONFIG_SERIAL=y
    CONFIG_UART_ASYNC_API=y
    CONFIG_UART_0_NRF_TX_BUFFER_SIZE=1024
    
    CONFIG_CONSOLE=n
    CONFIG_UART_CONSOLE=n
    
    # Main thread.
    CONFIG_MAIN_STACK_SIZE=8192
    
    CONFIG_HEAP_MEM_POOL_SIZE=16384
    
    CONFIG_NEWLIB_LIBC=y
    

    And Uart buff settings:

    #define UART_RX_BUF_SIZE 200
    #define UART_TX_BUF_SIZE 1024
  • Hi 

    How long does it take for the "Not able to allocate UART receive buffer" error to appear? 

    Does it happen after a certain number of UART packets, or does it happen right away?

    To be honest this example is not designed very well, and using dynamic memory allocation for buffers like this is a very risky practice. It would be much safer to use a queue of buffers or a ring buffer to handle the UART buffers, to avoid problems like memory fragmentation, and to avoid having to use the heap for UART data. 

    I would strongly recommend changing the way these buffers are handled. I am planning to make an example for this myself, but unfortunately I don't know when I will be able to do this since I also have a lot of other cases to handle. 

    Best regards
    Torbjørn

  • Occurs immediately after the connection is established.

    The settings are based on peripheral_uart and have not been changed too much.

    And the same code can run normally on nRF2840, Then why can't it run on nRF52833.

  • Hi 

    I was able to reproduce the issue based on your code, and after debugging this for a bit it seems that the issue is indirectly caused by the UART driver never freeing any of the buffers. 

    The buf_release variable is never set to true in mt_uart.c, and for this reason the receive buffers are never freed by the UART_RX_BUF_RELEASED event. 

    Why this only happens for the nRF52833 and not the nRF52840 I do not understand, the issue should be the same for both. 

    I will spend some more time with this tomorrow and try to get to the bottom of it. 

    By the way, there seems to be a bug in the UART_RX_RDY event, where the following two lines were changed from the original example:

                } else if ((evt->data.rx.buf[rx_buf->len - 1] == '\r'&&
                           (evt->data.rx.buf[rx_buf->len - 1] == '\n')) {
    The original example used or, while this was changed to and. (&& instead of ||)
    I tried to change this, but it did not help with the memory free issue. 
    Best regards
    Torbjørn
Reply
  • Hi 

    I was able to reproduce the issue based on your code, and after debugging this for a bit it seems that the issue is indirectly caused by the UART driver never freeing any of the buffers. 

    The buf_release variable is never set to true in mt_uart.c, and for this reason the receive buffers are never freed by the UART_RX_BUF_RELEASED event. 

    Why this only happens for the nRF52833 and not the nRF52840 I do not understand, the issue should be the same for both. 

    I will spend some more time with this tomorrow and try to get to the bottom of it. 

    By the way, there seems to be a bug in the UART_RX_RDY event, where the following two lines were changed from the original example:

                } else if ((evt->data.rx.buf[rx_buf->len - 1] == '\r'&&
                           (evt->data.rx.buf[rx_buf->len - 1] == '\n')) {
    The original example used or, while this was changed to and. (&& instead of ||)
    I tried to change this, but it did not help with the memory free issue. 
    Best regards
    Torbjørn
Children
  • Okay, I overlooked this change, but this does not affect the error. I know it may be caused by memory, but I haven't identified the problem and haven't found how to solve it.

    Hope you can help to solve it as soon as possible, thank you very much!

  • Hi 

    I spent some more time with it today. It appears the UART_RX_DISABLED event occurs extremely frequently when running the example on the nRF52833, and this is causing a lot more buffers to be allocated than you free. Eventually this will lead to the heap filling up, and you won't be able to allocate any more buffers. 

    Why the UART driver behaves like this on the nRF52833 I do not yet know. I tested it on the nRF52840 as well and confirmed that this device does not exhibit the same behavior. 

    Tomorrow I will try to set up a more simple UART example in order to debug what is happening with the UART driver when running it on the nRF52833. 

    Best regards
    Torbjørn

  • Hi 

    Sorry for the long delay. It has been some very busy weeks, and I only had limited time to test this out. 

    After doing more testing on my side it seems like most of the issues I have seen are caused a couple of factors:

    1) The fact that the nRF9160DK runs at 1.8V by default. In order to configure the board to 3.0V (to be compatible with the nRF52 kits) the SW1 switch must be set to the 3V setting. 

    2) When running UART communication without the external high frequency clock you will eventually encounter a framing errors, which causes problems for reception when using the Zephyr driver. 

    I solved this issue by making sure to request the high accuracy HF crystal to be enabled in order to ensure that the UART baudrate is as accurate as possible:

    int clocks_start(void)
    {
    	int err;
    	int res;
    	struct onoff_manager *clk_mgr;
    	struct onoff_client clk_cli;
    
    	clk_mgr = z_nrf_clock_control_get_onoff(CLOCK_CONTROL_NRF_SUBSYS_HF);
    	if (!clk_mgr) {
    		printk("Unable to get the Clock manager\n");
    		return -ENXIO;
    	}
    
    	sys_notify_init_spinwait(&clk_cli.notify);
    
    	err = onoff_request(clk_mgr, &clk_cli);
    	if (err < 0) {
    		printk("Clock request failed: %d\n", err);
    		return err;
    	}
    
    	do {
    		err = sys_notify_fetch_result(&clk_cli.notify, &res);
    		if (!err && res) {
    			printk("Clock could not be started: %d\n", res);
    			return res;
    		}
    	} while (err);
    
    	printk("HF clock started\n");
    	return 0;
    }

    2b) I believe the memory allocation scheme used in the example doesn't handle UART framing errors very well, as it will not free all the previously allocated memory when this happens. 

    In case of framing errors it is necessary to ensure that the receive buffers are freed, and the UART must be enabled again. 

    That said, if you follow my advice above hopefully the framing errors will not occur like they did before. 

    Best regards
    Torbjørn

  • Sorry, I didn't see your reply until recently due to some other reasons, I'll try it when I have time.

    Thanks very much!

  • Hi 

    No problem, just let me know if you have any more questions or comments after you have time to take a look. 

    Also, I made my own little UART example here to show a different way of handling the TX and RX buffering. 

    Best regards
    Torbjørn

Related