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

nrfx_uarte_rx Bytes disappearing

Softdevice 6.1.1

SDK 15.3

We have been using the nrfx_uart driver but realized we need to have multiple instances on our new hardware so have changed to using nrfx_uarte driver and now we are losing bytes when Receiving.

Our UART messaging protocol is as follows: 

[Type] [Length] [Data]

We do either 1 of these 3 things on the event callback (depending on our state e.g. if we have Type we then get length, if we have Length we get remaining etc...)

1. nrfx_uart_rx(&instance, buffer, 1); -> get the Type of 1 byte

2. nrfx_uart_rx(&instance, buffer, 1); -> get the length of renaming data

3. nrfx_uart_rx(&instance, buffer, length); -> get remaining data

This was working perfectly using the nrfx_uart driver but does not work using nrfx_uarte

an example message would be sent from a Linux machine  and looks like this -> { 0x05, 0x0F, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, }

Message Type 5, has a length of 15

I think i don't have good enough understanding of the difference between nrfx_uart_rx and nrfx_uarte_rx?? what is the difference between the two? and why would i not be able to receive a message like the above? i find it happens with messages that are larger than 8 bytes

Any help would be appreciated.

Regards,

David Hutchinson

Parents
  • Hi David, 

    Could you show your full code ? Could you describe the exact issue you are observing ? Did you use HWFC ? 


    Both nrfx_uart and nrfx_uarte support multiple instances. The main difference here is that the nrfx_uart uses the legacy UART when the nrfx_uarte uses the UART with EasyDMA. UART with EasyDMA can access the memory without the CPU involved. 

    Please note that in SDK v16 we provided an advanced UARTE library (which provide flexible RX mode with timeout). Have a look here.

Reply
  • Hi David, 

    Could you show your full code ? Could you describe the exact issue you are observing ? Did you use HWFC ? 


    Both nrfx_uart and nrfx_uarte support multiple instances. The main difference here is that the nrfx_uart uses the legacy UART when the nrfx_uarte uses the UART with EasyDMA. UART with EasyDMA can access the memory without the CPU involved. 

    Please note that in SDK v16 we provided an advanced UARTE library (which provide flexible RX mode with timeout). Have a look here.

Children
  • Not using HWFC

    I Realized i am getting an Overrun error.

    this is very easy to replicate:

    
    static void uart_event_handler(nrfx_uarte_event_t const * p_event, void * p_context){
        switch (p_event->type) {
    	case NRFX_UARTE_EVT_RX_DONE: {
    			err = nrfx_uarte_rx(inst, buffer, 1);
    		}break;
    	default:
    		return;
    	}
    }
    
    
    void init(){
        nrfx_uarte_config_t uart_config = NRFX_UARTE_DEFAULT_CONFIG;
    
    	uart_config.p_context = instance;
    	uart_config.pselcts =   pins.cts;
    	uart_config.pselrts =   pins.rts; 
    	uart_config.pselrxd =   pins.rxd; 
    	uart_config.pseltxd =   pins.txd; 
    
    	err = nrfx_uarte_init(inst, &uart_config, uart_event_handler);
    	
    	//start by just trying to received 1 byte (the type)
    	err = nrfx_uarte_rx(inst, buffer, 1);
    	
    }

    then send more than 8 bytes over a Terminal from PC and this will cause an overrun error.. it only happens when sending 8 bytes or more.. i find that sending 7 or < its fine...

    Regards,

    David Hutchinson

  • Hi David, 

    You are using the EasyDMA with just 1 byte. And without the HWFC the UART buffer is capable of receiving 4 more bytes before it's overflowed. What I suspect is that the CPU was too slow and didn't setup the buffer for the payload fast enough. Do you have any activity that can cause a long latency ? 

    Which baudrate are you using ? Could you try to reduce the baudrate to check if the size of the message can be longer before it overrun ? 

    nrfx_uarte_rx() supports double buffer. What you can do is to call nrfx_uarte_rx() twice to setup 2 buffer areas in RAM. If you can move the Length byte to the first byte and the TYPE byte to the second, then you can prepare the second buffer for the payload when you receive the length. (check the description of the nrfx_uarte_rx)

    But the better solution is to use libuart, You can setup a very large buffer and can have a timeout. This way you wouldn't have any problem if the CPU being hang for a long period. 

  • I have decided to use HWFC, and that seems to work.. However i can only get it working on a Devkit talking over USB to my PC..

    When i try and use it with a PCB i have that has 2 NRF52840 chips connected together it does not work.. Is there any sort of "initialization" needed for HWFC to work? Do i need to do anything special with the RTS and CTS pins, other than hook them up?

    Regards,

    David Hutchinson

  • Hi David, 

    Please make sure you configured the GPIO pins with correct configuration (input : RXD, CTS; output, no pull: TXD, RTS). This is done automatically in the nrf_uarte driver. 

    How did you define the RTS and CTS on the peers  ? Note that they have to be inverted on the peers. So the RTS on one side have to connect to CTS on the other side and vice versa. 

Related