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

Delay before starting DMA'd UART transfer

I need to send data over ModBus-RTU (basically RS485) from an nRF52840. For this, I use uarte. The transceiver's transmit enable input is controlled through a GPIO pin, which in turn is controlled from the PPI (NRF_UARTE_EVENT_TXSTARTED and  NRF_UARTE_EVENT_TXSTOP events). When I check on the scope, I see a varying time between the enable pin being raised and the start of the actual transfer. For example: in the below capture, the delay between TXD (in blue) and the enable pin (in red) is 23.67 usec, This delay varies from 0 up to one bittime (I've seen a 103 usec delay when transmitting on 9600 bps).

Can I remove these delays or otherwise at least stabilize them so that they always are the same?

This is my code for initialization:

void rs485_init ( void )
{
    uint32_t task_addr;
    uint32_t event_address;
    static bool _init_done = false;
    nrfx_uarte_config_t uarte_config = NRFX_UARTE_DEFAULT_CONFIG;
    uarte_config.pseltxd  = MODBUS_TX_PIN;
    uarte_config.pselrxd  = MODBUS_RX_PIN;
    uarte_config.hwfc     = NRF_UARTE_HWFC_DISABLED;

    nrfx_gpiote_out_config_t nrfx_gpiote_out_config = NRFX_GPIOTE_CONFIG_OUT_TASK_TOGGLE(0);

    uarte_config.baudrate = NRF_UARTE_BAUDRATE_9600;
    uarte_config.parity = NRF_UARTE_PARITY_INCLUDED;
    
    if (_init_done) nrfx_uarte_uninit(&uarte); 
    APP_ERROR_CHECK(nrfx_uarte_init( &uarte, &uarte_config, uarte_event_handler)); // Init in non-blocking mode

    if ( !nrfx_gpiote_is_init() ) 
    {
        nrfx_gpiote_init();
    }
    else
    {
        nrfx_gpiote_out_uninit( MODBUS_RTS_PIN );
    }

    // Initialize the RTS pin as output, to be driven from UART TX via PPI
    APP_ERROR_CHECK(nrfx_gpiote_out_init( MODBUS_RTS_PIN, &nrfx_gpiote_out_config ));
    nrfx_gpiote_out_task_enable( MODBUS_RTS_PIN );

    // Setup PPI to set enable on start of transmission
    APP_ERROR_CHECK( nrfx_ppi_channel_alloc( &_ppi_channel_start ) ); 
    event_address = nrfx_uarte_event_address_get( &uarte, NRF_UARTE_EVENT_TXSTARTED );
    task_addr = nrfx_gpiote_out_task_addr_get( MODBUS_RTS_PIN );
    APP_ERROR_CHECK( nrfx_ppi_channel_assign( _ppi_channel_start, event_address, task_addr ) );
    nrfx_ppi_channel_enable( _ppi_channel_start );

    // Setup PPI to clear enable on end of transmission
    APP_ERROR_CHECK( nrfx_ppi_channel_alloc( &_ppi_channel_stop ) ); 
    event_address = nrfx_uarte_event_address_get( &uarte, NRF_UARTE_EVENT_TXSTOPPED );
    task_addr = nrfx_gpiote_out_task_addr_get( MODBUS_RTS_PIN );
    APP_ERROR_CHECK( nrfx_ppi_channel_assign( _ppi_channel_stop, event_address, task_addr ) );
    nrfx_ppi_channel_enable( _ppi_channel_stop );

    // Receiver initialization removed for brevity

    _init_done = true;
    NRF_LOG_INFO( "RS485 initialized" );
}

Parents
  • Hi,

     

    The transceiver's transmit enable input is controlled through a GPIO pin, which in turn is controlled from the PPI (NRF_UARTE_EVENT_TXSTARTED and  NRF_UARTE_EVENT_TXSTOP events). When I check on the scope, I see a varying time between the enable pin being raised and the start of the actual transfer. For example: in the below capture, the delay between TXD (in blue) and the enable pin (in red) is 23.67 usec, This delay varies from 0 up to one bittime (I've seen a 103 usec delay when transmitting on 9600 bps).

    Your code shows that you set/clr a GPIOTE OUT task based on events _TXSTOPPED and _TXSTARTED.

    How do you actually stop and start the UARTE peripheral using TASKS_START and TASKS_STOP?

      

    PS: Looks like there's a picture missing?

     

    Kind regards,

    Håkon

Reply
  • Hi,

     

    The transceiver's transmit enable input is controlled through a GPIO pin, which in turn is controlled from the PPI (NRF_UARTE_EVENT_TXSTARTED and  NRF_UARTE_EVENT_TXSTOP events). When I check on the scope, I see a varying time between the enable pin being raised and the start of the actual transfer. For example: in the below capture, the delay between TXD (in blue) and the enable pin (in red) is 23.67 usec, This delay varies from 0 up to one bittime (I've seen a 103 usec delay when transmitting on 9600 bps).

    Your code shows that you set/clr a GPIOTE OUT task based on events _TXSTOPPED and _TXSTARTED.

    How do you actually stop and start the UARTE peripheral using TASKS_START and TASKS_STOP?

      

    PS: Looks like there's a picture missing?

     

    Kind regards,

    Håkon

Children
  • Looks like there's a picture missing?

    I can see the picture from my PC, uploaded to your servers and included it here. Anyway, it's just an image of the scope's stream showing there's a 23-something usec delay between the GPIO pin rising and TXD falling for the startbit.

    I start the transmission of the uart through nrfx_uarte_tx().

  • I would hazard a guess that the baud rate prescaler is not cleared when simply doing Start and Stop actions and therefore up to a single bit time of jitter from STARTTX to start bit active would be inevitable; however maybe unitit() and init() the UARTE before each transfer would clear the baud rate prescaler. Worth a test; a nuisance to apply but it would perhaps reduce the jitter.

    The alternative is to read the secret prescaler register and wait until it reaches a specific count before triggering the STARTTX, or use a parallel timer for the situation where the secret register is unknown or non-existent.

    To find the secret register (assuming it exists) do repeated breaks and look at any UARTE hardware registers changing in a linear fashion with the slowest possible baud rate.

    Edit: Another option may be to simply rewrite the BAUDRATE register with the same baud rate value; the nRF52 chip designers may have made that generate a prescaler reset to 0.

    Edit 2: I checked and there is no secret prescaler register visible in the memory block for the Uart. I haven't tried the rewrite baud register trick yet, but will try to find time later

  • Hi,

     

    jev said:
    I can see the picture from my PC, uploaded to your servers and included it here. Anyway, it's just an image of the scope's stream showing there's a 23-something usec delay between the GPIO pin rising and TXD falling for the startbit.

    My apologies for the inconvenience, but could you re-upload the picture? I reported this incident to the web admins, as the picture itself is not available at my end.

     

    Kind regards,

    Håkon 

  • Hi,

    Håkon has been on vacation so I have taken over this case. Did you have time to test the recomendations from user ? Are you still struggling with this or can I close this case?

    Kind regards,

    Marjeris

Related