UART ERRORSRC register break detection failed

Hello Jared,

the previous ticket find under the following link is locked. So I decided to open a new one. 

https://devzone.nordicsemi.com/f/nordic-q-a/80312/uart-break-detection-failed

Your last answer was:

The reset value is 0 for the ERRORSRC register. Setting it to 0x0C will set the framing and break bit to present. Could you instead modify the nrf_uarte_errorsrc_get_and_clear() by first checking which bit that is high and then resetting it by writing a 0 to the register?

That´s not the behavior of the ERRORSRC register. I tried to write in a clear ERRORSRC register 0xC but nothing changed, the content of the register is still 0. After sending a break from a peer device, the content of the ERRORSRC register is 0xC. After writing 0x4 to the register, the content is 0x8 and after writng 0x8 to the register then the content is 0. That means that individual bits in the register can only be cleared by writing a 1 on the individual bit position. Thats exactly what the funtction "nrf_uare_errorsrc_get_and_clear" does!

Your last question was:

Could you elaborate on the necessity for the delay?

With a baudrate of 9600 Baud a minimum delay of 70us was necessary to get a reliable break detection. For security reason, I will use 100us.

__STATIC_INLINE uint32_t nrf_uarte_errorsrc_get_and_clear(NRF_UARTE_Type * p_reg)
{
    nrf_delay_us(100);
    uint32_t errsrc_mask = p_reg->ERRORSRC;
    p_reg->ERRORSRC = errsrc_mask;
    return errsrc_mask;
}

Best Regards

Rainer

Parents
  • Hi,

    That´s not the behavior of the ERRORSRC register. I tried to write in a clear ERRORSRC register 0xC but nothing changed, the content of the register is still 0. After sending a break from a peer device, the content of the ERRORSRC register is 0xC. After writing 0x4 to the register, the content is 0x8 and after writng 0x8 to the register then the content is 0. That means that individual bits in the register can only be cleared by writing a 1 on the individual bit position. Thats exactly what the funtction "nrf_uare_errorsrc_get_and_clear" does!

    You're actually totally correct on this one. I forget how the ERRORSRC register functions, in that the register is read/write one to clear.

    I'm still not confident that the break bit is ignored if the program enters the  nrf_uarte_errorsrc_get_and_clear() to clear the framing bit and a break bit is set at the same time. If the break bit is set at the same time then 

    uint32_t errsrc_mask = p_reg->ERRORSRC;

    will return 0b1100 (0xC). 

    p_reg->ERRORSRC = errsrc_mask;

    Will then indeed clean both break and framing bit by writing a 1. But it will return 0b1100. Subsequently another call will be done to nrf_uarte_errorsrc_get_and_clear() since the break bit was set during the clearing of the framing bit. But since the break bit has already been cleared, this has no effect. But there should be no loss of the break bit being set since it was returned with the framing bit on the previous call to  nrf_uarte_errorsrc_get_and_clear(). Are you checking if the break bit is set somewhere in your code, or have you just tested with the debugger and breakpoints? If you're are checking it in the code then please share that part. Could you try modifying the nrf_uarte_errorsrc_get_and_clear() so that you check if the break bit is set every time you enter the handler right before you clear it? Something similar like this:

        if(errsrc_mask & (1<<3))
        {
                nrf_gpio_cfg_output(LED_1);
                nrf_gpio_pin_clear(LED_1);
            
        }

    It should light up LED_1 on the development kit if the break bit is set. Add it right after you read the register and right after you clear it.

    best regards
    Jared 

Reply
  • Hi,

    That´s not the behavior of the ERRORSRC register. I tried to write in a clear ERRORSRC register 0xC but nothing changed, the content of the register is still 0. After sending a break from a peer device, the content of the ERRORSRC register is 0xC. After writing 0x4 to the register, the content is 0x8 and after writng 0x8 to the register then the content is 0. That means that individual bits in the register can only be cleared by writing a 1 on the individual bit position. Thats exactly what the funtction "nrf_uare_errorsrc_get_and_clear" does!

    You're actually totally correct on this one. I forget how the ERRORSRC register functions, in that the register is read/write one to clear.

    I'm still not confident that the break bit is ignored if the program enters the  nrf_uarte_errorsrc_get_and_clear() to clear the framing bit and a break bit is set at the same time. If the break bit is set at the same time then 

    uint32_t errsrc_mask = p_reg->ERRORSRC;

    will return 0b1100 (0xC). 

    p_reg->ERRORSRC = errsrc_mask;

    Will then indeed clean both break and framing bit by writing a 1. But it will return 0b1100. Subsequently another call will be done to nrf_uarte_errorsrc_get_and_clear() since the break bit was set during the clearing of the framing bit. But since the break bit has already been cleared, this has no effect. But there should be no loss of the break bit being set since it was returned with the framing bit on the previous call to  nrf_uarte_errorsrc_get_and_clear(). Are you checking if the break bit is set somewhere in your code, or have you just tested with the debugger and breakpoints? If you're are checking it in the code then please share that part. Could you try modifying the nrf_uarte_errorsrc_get_and_clear() so that you check if the break bit is set every time you enter the handler right before you clear it? Something similar like this:

        if(errsrc_mask & (1<<3))
        {
                nrf_gpio_cfg_output(LED_1);
                nrf_gpio_pin_clear(LED_1);
            
        }

    It should light up LED_1 on the development kit if the break bit is set. Add it right after you read the register and right after you clear it.

    best regards
    Jared 

Children
  • Hello Jared,

    Could you try modifying the nrf_uarte_errorsrc_get_and_clear() so that you check if the break bit is set every time you enter the handler right before you clear it?

    That´s now my function:

    __STATIC_INLINE uint32_t nrf_uarte_errorsrc_get_and_clear(NRF_UARTE_Type * p_reg)
    {
        //nrf_delay_us(100);
    
        uint32_t errsrc_mask = p_reg->ERRORSRC;
    
        if(errsrc_mask & (1<<3))
        {
            nrf_gpio_cfg_output(0);
            nrf_gpio_pin_clear(0);
        }
    
        p_reg->ERRORSRC = errsrc_mask;
    
        uint32_t errsrc_mask_tmp = p_reg->ERRORSRC;
    
        if(errsrc_mask_tmp & (1<<3))
        {
            nrf_gpio_cfg_output(2);
            nrf_gpio_pin_clear(2);
        }
    
        return errsrc_mask;
    }

    After each test, when a led lights up, I restarted the device. LED2 never lights up. LED1 sometimes lights up. I made 5 test cycles. I had to fire the break condition from the peer device 25, 13, 77, 21, 17 times until LED1 lights up.

    Then I inserted my 100us delay at the beginning of the function. I made 10 test cycles. In all test cycles LED1 immediately lights up after sending one break condition from the peer device.

    Best Regards,

    Rainer

  • Hi there,

    Ok. Thank you for the report.

    I'll take a closer look at it and see if I'm able to reproduce this on my end.

    It seems that you were able to find a solution for you project, which is good Slight smile

    regards

    Jared 

Related