UART_RX_RDY not called after RESUME

Hello,

I am working on a project were two MCU's need to communicate with each other via UART. I am using async UART. I am stuck with this problem where after

PM_DEVICE_ACTION_RESUME call the uart_device is in Active state but UART_RX_RDY  is not called and I know for sure that there are incoming data. I am probably missing something obvious. 

To elaborate a little more about the specifics. The two MCU's are connected via UART and some GPIO's. The idea is that LTE module receives data, suspends UART driver, uplink the received data and go to PSM. To resume the UART device I used one GPIO with interrupt. When the other MCU pulls GPIO high an interrupt fires, resumes the UART device and waits for data. But instead I get UART_RX_STOPPED and UART_RX_DISABLED because the other MCU turned off its UART and now its pulling RX line low. 
I tried to uart_rx_enable after the PM_DEVICE_ACTION_RESUME but it returns error as expected because reception was never disabled. 
Everything works fine if I remove pm_device_action_run from UART driver and set other MCU to pull the nRF9160 RX pin high instead of low. That's why I am pretty sure that there is something missing in nRF9160 code not on the other MCU


Here are some code snippets how I enable/disable the driver. It's still a bit messy because I was testing what works and what doesn't:
static int gpioCallback(const struct device *dev, struct gpio_callback *cb, uint32_t pins)
{
    int err;
    err = pm_device_action_run(uart_dev, PM_DEVICE_ACTION_RESUME);
    if (err && err != -EALREADY)
    {
        // LOG_ERR("Call `pm_device_action_run` failed: %d", err);
    }

    if (!device_is_ready(uart_dev))
    {
        // LOG_ERR("Device not ready");
    }
    // LOG_INF("UART waked up");
}
    case UART_RX_RDY:
        size_t offset = evt->data.rx.offset;
        size = evt->data.rx.len;
        memcpy(rxBuf, &evt->data.rx.buf[offset], size);

        // Enable CoAP work to transmit newly received data
        k_work_schedule(workCoap, K_NO_WAIT);
        err = pm_device_action_run(uart_dev, PM_DEVICE_ACTION_SUSPEND);
        if (err && err != -EALREADY) 
        {
            LOG_ERR("Call `pm_device_action_run` failed: %d", err);
        }
        break;
Any ideas?
Parents
  • Hello,

    Have you tried enabling the receiver again after the UART_RX_DISABLED event?

    The UART_RX_STOPPED is raised if an error condition has been detected on the bus. For instance, if the receiver is enabled why the other MCU pulls the RX line low. 

    Best regards,

    Vidar

  • Hello Vidar,

    This is not the issue here. UART_RX_DISABLED  event is received when the incoming data are already missed. I tested this scenario:

    The other MCU never turns off its UART and it sends data to nRF9160 every 1 minute. So at startup the nRF9160 waits for first successful UART reception which is UART_RX_RDY  event and then puts uart_dev to suspended state. After few seconds I resume the uart_dev (thought maybe some timings might be the issue) and when the next message is sent from other MCU I never receive the UART_RX_RDY  event. 

    I hope you understood the above situation description. Currently I am testing different approaches but still haven't found a solution.

    I thought that SUSPEND and RESUME would be as easy as calling:

     

            err = pm_device_action_run(uart_dev, PM_DEVICE_ACTION_SUSPEND);
            if (err && err != -EALREADY) 
            {
                LOG_ERR("Call `pm_device_action_run` failed: %d", err);
            }

    to suspend and

        err = pm_device_action_run(uart_dev, PM_DEVICE_ACTION_RESUME);
        if (err && err != -EALREADY)
        {
            // LOG_ERR("Call `pm_device_action_run` failed: %d", err);
        }

    to resume and I don't have to do anything else but seems like it is not the case here.

    Here is the config used for UART. I took it from lpuart example:

    CONFIG_UART_ASYNC_API=y
    CONFIG_UART_1_ASYNC=y
    CONFIG_UART_1_INTERRUPT_DRIVEN=n
    CONFIG_UART_1_NRF_HW_ASYNC=y
    CONFIG_UART_1_NRF_HW_ASYNC_TIMER=2
    CONFIG_UART_1_NRF_ASYNC_LOW_POWER=y
    CONFIG_NRFX_TIMER2=y

Reply
  • Hello Vidar,

    This is not the issue here. UART_RX_DISABLED  event is received when the incoming data are already missed. I tested this scenario:

    The other MCU never turns off its UART and it sends data to nRF9160 every 1 minute. So at startup the nRF9160 waits for first successful UART reception which is UART_RX_RDY  event and then puts uart_dev to suspended state. After few seconds I resume the uart_dev (thought maybe some timings might be the issue) and when the next message is sent from other MCU I never receive the UART_RX_RDY  event. 

    I hope you understood the above situation description. Currently I am testing different approaches but still haven't found a solution.

    I thought that SUSPEND and RESUME would be as easy as calling:

     

            err = pm_device_action_run(uart_dev, PM_DEVICE_ACTION_SUSPEND);
            if (err && err != -EALREADY) 
            {
                LOG_ERR("Call `pm_device_action_run` failed: %d", err);
            }

    to suspend and

        err = pm_device_action_run(uart_dev, PM_DEVICE_ACTION_RESUME);
        if (err && err != -EALREADY)
        {
            // LOG_ERR("Call `pm_device_action_run` failed: %d", err);
        }

    to resume and I don't have to do anything else but seems like it is not the case here.

    Here is the config used for UART. I took it from lpuart example:

    CONFIG_UART_ASYNC_API=y
    CONFIG_UART_1_ASYNC=y
    CONFIG_UART_1_INTERRUPT_DRIVEN=n
    CONFIG_UART_1_NRF_HW_ASYNC=y
    CONFIG_UART_1_NRF_HW_ASYNC_TIMER=2
    CONFIG_UART_1_NRF_ASYNC_LOW_POWER=y
    CONFIG_NRFX_TIMER2=y

Children
No Data
Related