What is the recommended UART SUSPEND sequence to use the PM_DEVICE_RUNTIME?

What is the recommended UART SUSPEND sequence to use the PM_DEVICE_RUNTIME?

I am having trouble using the PM capabilities with the UARTe driver.

I am developing on the 52833, using sdk 2.5.2 for UART0 w/UARTe driver.

My prj.conf has:
CONFIG_PM_DEVICE=y
CONFIG_PM_DEVICE_RUNTIME=y
CONFIG_PINCTRL=y
CONFIG_SERIAL=y
CONFIG_UART_ASYNC_API=y
CONFIG_BOOT_BANNER=n
CONFIG_CONSOLE=y
CONFIG_UART_CONSOLE=n
CONFIG_USE_SEGGER_RTT=y
CONFIG_RTT_CONSOLE=y

I use the RTT for my console and logs.  The RTT clearly illustrates that I'm disabling the UART but not Suspending...

The rest of the program is working except when I try to SUSPEND the UART in between transmissions.
uart_rx_enable() and uart_rx_disable() are working as expected.
I am handling flags in the ISR to keep it quick...
I do see the buffers being requested and released as expected.
I do see UART_RX_DISABLED when expected, as expected.
case UART_RX_DISABLED:      // receiver has been stopped, disabled or finished its operation (receive buffer filled)
    if (RX_DisableRequested) {
        RX_Enabled = false;
        printk("UART_RX_DISABLED - As Requested\r\n\n"); }


But, when I try to pm_device_action_run(uart, PM_DEVICE_ACTION_SUSPEND), it fails to successfully shutdown and then blocks me from doing an rx_enable()

Here is my procedure... What am I missing?

Thanks in advance!
Jim

void SuspendUART (void) {
    int ret;

    if (RX_Enabled) {
            if ((uart_rx_disable(uart)) < 0) {
                printk("\n UART RX Disable failed - SuspendUART\n");
                RX_Enabled = true;
            } else {
                printk("\n UART RX Disable - SuspendUART\n");
                RX_Enabled = false;
            }
    }
    if ((!PM_Suspend) && (!RX_Enabled)) {
        ret = pm_device_state_get(uart, &current_state);
        if (ret != PM_DEVICE_STATE_SUSPENDED) {             // UART is currently suspended, resume it if necessary
            if ((ret = pm_device_action_run(uart, PM_DEVICE_ACTION_SUSPEND)) != 0) {
                LOG_ERR("UART PM SUSPEND failed - SuspendUART");
            }
            k_msleep(100);
            ret = pm_device_state_get(uart, &current_state);
            if (ret == PM_DEVICE_STATE_SUSPENDED) {             // UART is currently suspended, resume it if necessary
                PM_Suspend = true;
                printk(" UART PM Suspend - SuspendUART\n");
            } else {
                PM_Suspend = false;
                printk(" UART PM Suspend FAIL - SuspendUART\n");
            }
        }
    }
}

 void ResumeUART (void) {
    int ret;
    ret = 0;
    if (PM_Suspend) {
        ret = pm_device_state_get(uart, &current_state);
        if (ret == PM_DEVICE_STATE_SUSPENDED)  {
            PM_Suspend = true;            // UART is currently suspended, resume it if necessary
            if (ret += pm_device_action_run(uart, PM_DEVICE_ACTION_RESUME) != 0) {
                // LOG_ERR("UART PM RESUME failed - 3");
                printk("UART PM Resume FAIL - SendTempC\n");
            }
        } else if (ret == PM_DEVICE_STATE_SUSPENDING) {
            PM_Suspend = true;
        } else {
            PM_Suspend = false;
            printk("UART PM Resume - SendTempC\n");
        }
        k_msleep(100);
        ret = pm_device_state_get(uart, &current_state);
        if (ret == PM_DEVICE_STATE_SUSPENDED)  {
            PM_Suspend = true;            // UART is currently suspended, resume it if necessary
            if (ret += pm_device_action_run(uart, PM_DEVICE_ACTION_RESUME) != 0) {
                // LOG_ERR("UART PM RESUME failed - 3");
                printk("UART PM Resume FAIL - SendTempC\n");
            }
        } else if (ret == PM_DEVICE_STATE_SUSPENDING) {
            PM_Suspend = true;
        } else {
            PM_Suspend = false;
            printk("UART PM Resume - SendTempC\n");
        }
    }
    if (!RX_Enabled) {
        RX_Enabled = true;
        if (RX_Buffer1) {
            if (uart_rx_enable(uart, rx_buf2, sizeof rx_buf1, RECEIVE_TIMEOUT) != 0) {
                LOG_ERR("UART RX Enable failed - SendTempC rx_buf2");
                RX_Enabled = false;
            } else {
                printk(" UART RX Enable - SendTempC rx_buf2\r\n");
                RX_Buffer1 = false;
            }
        } else {
            if (uart_rx_enable(uart, rx_buf1, sizeof rx_buf1, RECEIVE_TIMEOUT) != 0) {
                LOG_ERR("UART RX Enable failed - SendTempC rx_buf1");
                RX_Enabled = false;
            } else {
                printk(" UART RX Enable - SendTempC rx_buf1\r\n");
                RX_Buffer1 = true;
            }
        }
    }
}


Parents
  • Hi Jim

    Hard to say what the problem would be here. Assuming you wait for the RX to be properly disabled, and any ongoing TX transactions are completed, it should be possible to suspend the UART. 

    Is there any chance you are trying to suspend the driver directly from the UART ASYNC callback? 

    Best regards
    Torbjørn


  • Thanks Torbjorn,  a week ago I thought maybe that was the problem and took my shutdown out of the DISABLED callback.  I didn't see any documentation that you shouldn't do the SUSPEND from the callback... but I removed it anyway.

    I only call SuspendUART() from the Main after all of the status flags are satisfied, indicating that we want to shut down and everything is ready (No TX in progress and RX Disabled)...

    All I get is PM SUSPEND failed.  Here is the code and the RTT output

    I must be missing something.


    void SuspendUART (void) {
        int ret;
        ret = 0;
        if ((!PM_Suspend) && PM_SuspendRequested && (!CurrentlyTransmitting) && RX_Enabled) {
            RX_DisableRequested = true;
            #ifdef UART_Enable_Disable
                if ((uart_rx_disable(uart)) < 0) {
                    // LOG_ERR("UART RX Disable failed - SuspendUART");
                    #ifdef SUSPEND_RESUME
                        printk("\nSuspendUART - RX Disable failed\n");
                    #endif
                } else {
                    #ifdef SUSPEND_RESUME
                        printk("\nSuspendUART - RX Disable Started\n");
                    #endif
                }
            #endif
        }
        #ifdef UART_PM_ENABLED
            if ((!PM_Suspend) && PM_SuspendRequested && (!CurrentlyTransmitting) && (!RX_Enabled)) {
                ret = pm_device_state_get(uart, &current_state);
                if (ret != PM_DEVICE_STATE_SUSPENDED) {             // UART is currently suspended, resume it if necessary
                    if ((ret = pm_device_action_run(uart, PM_DEVICE_ACTION_SUSPEND)) != 0) {
                        LOG_ERR("SuspendUART - PM SUSPEND failed");
                    }
                    k_msleep(100);
                    ret = pm_device_state_get(uart, &current_state);
                    if ((ret == PM_DEVICE_STATE_SUSPENDED) || (ret == PM_DEVICE_STATE_SUSPENDING)) {             // UART is currently suspended, resume it if necessary
                            PM_Suspend = true;
                            #ifdef SUSPEND_RESUME
                                printk("SuspendUART - PM Suspended\n");
                            #endif
                    } else {
                        PM_Suspend = false;
                        #ifdef SUSPEND_RESUME
                            printk("SuspendUART - PM Suspend FAIL\n");
                        #endif
                    }
                }
            }
        #else
            PM_Suspend = true;
        #endif
    }


    00>
    00> AT+RID
    00>  +RID ExecHandler    NexxState 5      3425B4152C8D
    00>  +OK ExecHandler    NexxState 6
    00>
    00> AT+NSTAT
    00>  +NSTAT ExecHandler    NexxState 7    BONDED_CONNECTED
    00>  +OK ExecHandler    NexxState 9
    00>  UART PM Suspend Requested - OK ConnRX
    00>
    00> SuspendUART - RX Disable Started
    00> UART_RX_DISABLED - As Requested
    00> SuspendUART - PM Suspend FAIL
    00> E: SuspendUART - PM SUSPEND failed
    00> SuspendUART - PM Suspend FAIL
    00> E: SuspendUART - PM SUSPEND failed
    00> SuspendUART - PM Suspend FAIL
    00> E: SuspendUART - PM SUSPEND failed
    00> SuspendUART - PM Suspend FAIL
    00> E: SuspendUART - PM SUSPEND failed
    00> SuspendUART - PM Suspend FAIL
    00> E: SuspendUART - PM SUSPEND failed
    00> SuspendUART - PM Suspend FAIL
    00> E: SuspendUART - PM SUSPEND failed
    00> SuspendUART - PM Suspend FAIL
    00> E: SuspendUART - PM SUSPEND failed
    00> SuspendUART - PM Suspend FAIL
    00> E: SuspendUART - PM SUSPEND failed
    00> SuspendUART - PM Suspend FAIL
    00>  ResumeUART - RX Enabled buf1
    00> UART_TX_ABORTED
    00>
    00> AT+SS16=12,0229
    00>  CPU DieTempC = 210     BearingTempC = 23.0     BearingTempF = 73.3     r = 10838
    00> UART_TX_ABORTED
    00>
    00> AT+SS16=12,0229

                        #ifdef SUSPEND_RESUME
                            printk("SuspendUART - PM Suspend FAIL\n");
                        #endif
                    }
                }
            }
        #else
            PM_Suspend = true;
        #endif
    }
  • Hi Jim

    Did you check which error code was returned?

    Could you try to step into the pm_device_action_run(..) call using the debugger and see where it ends up? 
    If you can figure out where the error code is returned we might be able to understand the root cause. 

    Best regards
    Torbjørn

Reply Children
No Data
Related