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

app_timer_irq_priority interfering with UARTE0 & UARTE1

I am currently making a program that will interpret serial commands from UARTE1 and then send + read something from the other (UARTE0). Previously, when I have been using a single UARTE I have had no problem setting up an app_timer and waiting for it to expire while waiting for a full "message" from the UARTE (indicated by a newline).

static ret_code_t myTimerTimeoutSetup(uint32_t timeout_ms, my_timer_timeout_t* p_tout_ctx)
{
    uint32_t ticks = APP_TIMER_TICKS(timeout_ms);

    if (ticks < APP_TIMER_MIN_TIMEOUT_TICKS)
    {
        p_tout_ctx->expired = true;
        return NRF_SUCCESS;
    }

    ret_code_t ret = app_timer_create(&my_timer_id,
        APP_TIMER_MODE_SINGLE_SHOT,
        fc_adafruitFonaTimeoutHandler);

    APP_ERROR_CHECK(ret);

    // If the timer is failed to be created, return the error code
    if (ret != NRF_SUCCESS)
    {
        return ret;
    }

    return app_timer_start(my_timer_id, ticks, p_tout_ctx);
}

much like is done in nrf_serial, I then have a statement such as: if (tout_ctx.expired) break; in my while loop to break when time is up.

Now that I am using both UARTEs, both of them freeze (when they should transmitting data) until the timer has expired, on which they will finish transmitting (nrf_serial_write). I have also had trouble with the timer never expiring if the interrupt priority is set to the default 6.

Is this an IRQ priority issue?

Thanks very much

Parents
  • NB: We are really short staffed due to Summer Holidays in Norway. You must expect some extra delay in technical questions these days, I am afraid. I am sorry for the inconvenience.

    I will try to get back to this tomorrow. 

    Note: It does sound like an IRQ issue. Something is blocked, waiting for the chance to run. If they are waiting for eachother, that may be the issue. 

    1: Have you checked the SDK16\examples\peripheral\serial_uartes example?

    2: Have you tried to use non-blocking calls with an event handler?

  • Thanks for the reply, Edvin. No worries about slow replies!

    My program is based off this example. Both APP_TIMER and UARTE priority are originally set to 6. Lowering the APP_TIMER priority (raising it's importance) solves the issue I mentioned about the timer never expiring, however the freezing UARTE problem still remains.

    I have tried adding a timeout to the nrf_serial_write so that it blocks all code until the write has completed but that has not made a difference to the transmission not finishing. I usually have the timeout set to 0 to run in non-blocking mode.

    Here is the order in which things are called. I have indicated things which I can see on the serial in comments :)

    serial_status_t serialFunction(nrf_serial_t serial, char* send_message, char* buffer, uint32_t timeout_ms, uint32_t serial_timeout_ms)
    {
        (void)nrf_serial_write(&serial, send_message, strlen(send_message), NULL, serial_timeout_ms); // IS NOT PRINTED UNTIL TIMER EXPIRES, EXCEPT FOT THE FIRST CHARACTER
        (void)nrf_serial_write(&serial, "\r\n", strlen("\r\n"), NULL, serial_timeout_ms);
        (void)nrf_serial_flush(&serial, serial_timeout_ms);  
        
        char read_character;
        uint8_t read_index = 0;
        uint32_t read_check;
    
        buffer[0] = 0;
    
        serial_timeout_t tout_ctx =
        {
                .expired = false,
        };
    
        ret_code_t ret = serialTimeoutSetup(timeout_ms, &tout_ctx);
    
        if (ret != NRF_SUCCESS)
        {
            return FAIL;
        }
    
        
    
        while (true)
        {
            read_check = nrf_serial_read(&serial, &read_character, sizeof(read_character), NULL, serial_timeout_ms);
            if (tout_ctx.expired) // Took top long for a response, timeout
            {
                (void)app_timer_stop(fc_serial_timer_id);
                return FLEXI_COMMS_SERIAL_TIMEOUT;
            }
            else if (read_check != NRF_SUCCESS) // Skip the rest of the code for efficiency
            {
                continue;
            }
            // stuff to process incoming read_character
        }
    }
    
    // Lines in program which are being called
    
        nrf_serial_write(&serial_uarte1, command, strlen(command), NULL, 0);
        nrf_serial_write(&serial_uarte1, message_cr_lf, strlen(message_cr_lf), NULL, 0); // IS NOT PRINTED UNTIL TIMER EXPIRES
        
        
        char reply[255];
    
        serialFunction(serial_uarte0, "testing, send me a reply", reply, 5000, 0);

    so in my terminals I see:

    UARTE1                            |                          UARTE0               (indicating which uarte to which terminal screens)

    command                          |     t

    *Waits until timer has expired*

    command\r\n                     |     test, send me a reply\r\n

Reply
  • Thanks for the reply, Edvin. No worries about slow replies!

    My program is based off this example. Both APP_TIMER and UARTE priority are originally set to 6. Lowering the APP_TIMER priority (raising it's importance) solves the issue I mentioned about the timer never expiring, however the freezing UARTE problem still remains.

    I have tried adding a timeout to the nrf_serial_write so that it blocks all code until the write has completed but that has not made a difference to the transmission not finishing. I usually have the timeout set to 0 to run in non-blocking mode.

    Here is the order in which things are called. I have indicated things which I can see on the serial in comments :)

    serial_status_t serialFunction(nrf_serial_t serial, char* send_message, char* buffer, uint32_t timeout_ms, uint32_t serial_timeout_ms)
    {
        (void)nrf_serial_write(&serial, send_message, strlen(send_message), NULL, serial_timeout_ms); // IS NOT PRINTED UNTIL TIMER EXPIRES, EXCEPT FOT THE FIRST CHARACTER
        (void)nrf_serial_write(&serial, "\r\n", strlen("\r\n"), NULL, serial_timeout_ms);
        (void)nrf_serial_flush(&serial, serial_timeout_ms);  
        
        char read_character;
        uint8_t read_index = 0;
        uint32_t read_check;
    
        buffer[0] = 0;
    
        serial_timeout_t tout_ctx =
        {
                .expired = false,
        };
    
        ret_code_t ret = serialTimeoutSetup(timeout_ms, &tout_ctx);
    
        if (ret != NRF_SUCCESS)
        {
            return FAIL;
        }
    
        
    
        while (true)
        {
            read_check = nrf_serial_read(&serial, &read_character, sizeof(read_character), NULL, serial_timeout_ms);
            if (tout_ctx.expired) // Took top long for a response, timeout
            {
                (void)app_timer_stop(fc_serial_timer_id);
                return FLEXI_COMMS_SERIAL_TIMEOUT;
            }
            else if (read_check != NRF_SUCCESS) // Skip the rest of the code for efficiency
            {
                continue;
            }
            // stuff to process incoming read_character
        }
    }
    
    // Lines in program which are being called
    
        nrf_serial_write(&serial_uarte1, command, strlen(command), NULL, 0);
        nrf_serial_write(&serial_uarte1, message_cr_lf, strlen(message_cr_lf), NULL, 0); // IS NOT PRINTED UNTIL TIMER EXPIRES
        
        
        char reply[255];
    
        serialFunction(serial_uarte0, "testing, send me a reply", reply, 5000, 0);

    so in my terminals I see:

    UARTE1                            |                          UARTE0               (indicating which uarte to which terminal screens)

    command                          |     t

    *Waits until timer has expired*

    command\r\n                     |     test, send me a reply\r\n

Children
No Data
Related