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

UART break detection failed

Hello, 

my application requires a reliable break detection (The serial data input is '0' for longer than the length of a data
frame) sent from a peer device on the UART RxD line. 

I use the SDK15.3.0 and expanded the code in nrf_serial.c/h so that I get the error condition (overrun, parity, framing, break) in the uart_rxd_event_handler.

But I never get the break condition, only a few framing error conditions in series. I checked the run-time behavior with a debugger. Setting a breakpoint directly at the beginning of the isr "uarte_irq_handler", and after sending the break condition with the peer device, I can see that both bits, break and framing, in the ERRORSRC register are set.

Then I removed the resetting (p_reg->ERRORSRC = errsrc_mask) of the bits in the ERRORSRC register in the function "nrf_uarte_errorsrc_get_and_clear". I also removed the breakpoint in the debugger at the beginning of the isr. After a reboot and sending the break condition with the peer device, both bits (break and framing) should be set in the ERRORSRC register. I stopped the debugger anywhere and checked the ERRORSRC register. Only the framing bit is set in the ERRORSRC register.

Then I removed additioniallly the reading (errsrc_masK = p_reg->ERRORSRC) of the ERRORSRC register in the function "nrf_uarte_errorsrc_get_and_clear". After a reboot and sending the break condition with the peer device, I stopped the debugger anywhere and checked the ERRORSRC register. Now both bits, break and the framing bits are set in the ERRORSRC register.

I read somewhere, that first a framing error is detected and afterwards a break condition is detected when a break condition is received from a peer device. All above means, that the framing interrupt with the following reading of the ERRORSRC register prevents the setting of the break bit in the ERRORSRC register.

Could you please verify my result and instruct me how to handle a reliable break detection?!?!

Parents
  • Hi,

    I read somewhere, that first a framing error is detected and afterwards a break condition is detected when a break condition is received from a peer device. All above means, that the framing interrupt with the following reading of the ERRORSRC register prevents the setting of the break bit in the ERRORSRC register.

    Not quite, the framing is effectively always generated before a break condition, but the nrf_uarte_errorsrc_get_and_clear() shouldn't clear the break bit in the ERRORSRC register when a framing error has happened. 

    But I never get the break condition, only a few framing error conditions in series. I checked the run-time behavior with a debugger. Setting a breakpoint directly at the beginning of the isr "uarte_irq_handler", and after sending the break condition with the peer device, I can see that both bits, break and framing, in the ERRORSRC register are set.

    So you can see that the break bit being set in the uarte_irq_handler but not in your uart_rxd_event_handler() which you have added to the serial lib?? Could you post code that shows how you forward the ERRORSRC error to your modified handler? 

    regards
    Jared 

Reply
  • Hi,

    I read somewhere, that first a framing error is detected and afterwards a break condition is detected when a break condition is received from a peer device. All above means, that the framing interrupt with the following reading of the ERRORSRC register prevents the setting of the break bit in the ERRORSRC register.

    Not quite, the framing is effectively always generated before a break condition, but the nrf_uarte_errorsrc_get_and_clear() shouldn't clear the break bit in the ERRORSRC register when a framing error has happened. 

    But I never get the break condition, only a few framing error conditions in series. I checked the run-time behavior with a debugger. Setting a breakpoint directly at the beginning of the isr "uarte_irq_handler", and after sending the break condition with the peer device, I can see that both bits, break and framing, in the ERRORSRC register are set.

    So you can see that the break bit being set in the uarte_irq_handler but not in your uart_rxd_event_handler() which you have added to the serial lib?? Could you post code that shows how you forward the ERRORSRC error to your modified handler? 

    regards
    Jared 

Children
  • Hello Jared,

    thanks for your reply. 

    Not quite, the framing is effectively always generated before a break condition, but the nrf_uarte_errorsrc_get_and_clear() shouldn't clear the break bit in the ERRORSRC register when a framing error has happened. 

    Yes, that shouldn´t happen. But the reading of the ERRORSRC register, triggered through the framing interrupt prevents the setting of the break bit in the ERRORSRC register. Inserting a delay in the function nrf_uarte_errorsrc_get_and_clear() helps a lot, Now I get the break condition event in my uart_rxd_event_handler(). The minimum delay for a reliable break detection is 70us. 

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

    With the knowledge that a break condition will be received, I changed the function nrf_uarte_errorsrc_get_and_clear() for a test case in such a way, that I does not read the ERRORSRC register but write the ERRORSRC register with the fixed value of 0x0C to reset the framing and break bits. This test works fine, I also get the break condition event (twice) in my uart_rxd_event_handler(). With this test it´s obvious, that the reading of the ERRORSRC register triggered through the framing error condition detection prevents the setting of the break bit in the ERRORSRC register. 

    __STATIC_INLINE uint32_t nrf_uarte_errorsrc_get_and_clear(NRF_UARTE_Type * p_reg)
    {
        //nrf_delay_us(70);
        //uint32_t errsrc_mask = p_reg->ERRORSRC;
        uint32_t errsrc_mask = 0x0c;
        p_reg->ERRORSRC = errsrc_mask;
        return errsrc_mask;
    }

    The delay of min 70us, which I inserted as a solution gives a timeslot in which the break bit can be set through the hardware in the ERRORSRC register.

    I would say, there is a hardware problem in the ERRORSRC register handling. A semaphore is missing when the hardware tries to set the break bit and the software simultaneously reads the ERRORSRC register.

    Best regards

    Rainer

    
    
  • Hi,

    Rainer303 said:
    but write the ERRORSRC register with the fixed value of 0x0C to reset the framing and break bits.

    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?

    Rainer303 said:

    The delay of min 70us, which I inserted as a solution gives a timeslot in which the break bit can be set through the hardware in the ERRORSRC register.

    Could you elaborate on the necessity for the delay?

    regards

    Jared 

Related