How Your USB device's suspend callback be called

 

User Space Entry:

    1 : sys file system
        Path: /sys/power
    2 : Find out what power management state the system support
        cat /sys/power/state
    3 : Made system enter into the state you specified
        echo disk > /sys/power/state

 

What does kernel do:

    1 :
        File : /kernel/power/main.c
        Function : pm_init
        Created the sys file system interface to give ability to user to control the system's state
    2 :
        File : /kernel/power/main.c
        Function : state_store
             : state_show
        is the function which executed the command from userspace   
            state_show handle the read request like cat /sys/power/state and
            state_store handle the write request like echo disk > /sys/power/state

    3 : Enter standy mode's function call sequence
        enter_state -> suspend_devices_and_enter -> dpm_suspend_start -> dpm_suspend -> device_suspend

drivers/base/power:
static int device_suspend(struct device *dev, pm_message_t state)
{
    int error = 0;

    down(&dev->sem);

    if (dev->class) {
        if (dev->class->pm) {
            pm_dev_dbg(dev, state, "class ");
            error = pm_op(dev, dev->class->pm, state);
        } else if (dev->class->suspend) {
            pm_dev_dbg(dev, state, "legacy class ");
            error = legacy_suspend(dev, state, dev->class->suspend);
        }
        if (error)
            goto End;
    }

    if (dev->type) {
        if (dev->type->pm) {
            pm_dev_dbg(dev, state, "type ");
            error = pm_op(dev, dev->type->pm, state);
        }
        if (error)
            goto End;
    }

    if (dev->bus) {
        if (dev->bus->pm) {
            pm_dev_dbg(dev, state, "");
            error = pm_op(dev, dev->bus->pm, state);
        } else if (dev->bus->suspend) {
            pm_dev_dbg(dev, state, "legacy ");
            error = legacy_suspend(dev, state, dev->bus->suspend);
        }
    }
 End:
    up(&dev->sem);

    return error;
}

    In this function, kernel try to call the device's suspend callback function to complete the suspend task. And class , type
    and bus are the driver model used by Linux.
    I will explain the sequence of device suspend in the USB subsystem later.


        Global Var: dpm_list
            The driver model core calls device_pm_add() when a device is registered.
            This will intialize the embedded device_pm_info object in the device and
            add it to the list of power-controlled devices. sysfs entries for controlling device
            power management will also be added

            device_add -> device_pm_add

USB system suspend process:
1 : What happened when one USB device plugs in
    USB subsystem starts a kernel thread which is called hub_thread to detect the USB device plug/unplug event.
   
usb/core/hub.c
int usb_hub_init(void)
{
    if (usb_register(&hub_driver) < 0) {
        printk(KERN_ERR "%s: can't register hub driver/n",
            usbcore_name);
        return -1;
    }

    khubd_task = kthread_run(hub_thread, NULL, "khubd");
    if (!IS_ERR(khubd_task))
        return 0;

    /* Fall through if kernel_thread failed */
    usb_deregister(&hub_driver);
    printk(KERN_ERR "%s: can't start khubd/n", usbcore_name);

    return -1;
}

    USB subsystem handle USB port status change event in the hub_events, and call routine
hub_port_connect_change if there is an plug/unplug event happeded.

    In hub_port_connect_change function ,  we should allocate a usb_device structure before
we start to acutally find a device. This need us call function usb_alloc_dev, and we can see following 3 lines
in this function :
   
    dev->dev.bus = &usb_bus_type;
    dev->dev.type = &usb_device_type;
    dev->dev.groups = usb_device_groups;

The definition of usb_device type is :

struct device_type usb_device_type = {
    .name =        "usb_device",
    .release =    usb_release_dev,
    .uevent =    usb_dev_uevent,
    .devnode =     usb_devnode,
    .pm =        &usb_device_pm_ops,
};
and the definiton of the usb_device bus is :

struct bus_type usb_bus_type = {
    .name =        "usb",
    .match =    usb_device_match,
    .uevent =    usb_uevent,
};

so regarding to the USB subsystem , the really worker in the device_supsend is :
    
    if (dev->type) {
        if (dev->type->pm) {
            pm_dev_dbg(dev, state, "type ");
            error = pm_op(dev, dev->type->pm, state);
        }
        if (error)
            goto End;
    }

According to the power management event PM_EVENT_SUSPEND, the pm_op handle it like this :

        if (ops->suspend) {
            error = ops->suspend(dev);
            suspend_report_result(ops->suspend, error);
        }
That is to say, USB subsystem will call usb_dev_suspend, the sequence is as following :

usb_dev_suspend -> usb_suspend -> usb_external_suspend_device -> usb_suspend_both -> usb_suspend_interface.

And finally, in the routine usb_suspend_interface, USB subsystem will call your own usb device's suspend function.

static int usb_suspend_interface(struct usb_device *udev,
        struct usb_interface *intf, pm_message_t msg)
{
    struct usb_driver    *driver;
    int            status = 0;

    /* with no hardware, USB interfaces only use FREEZE and ON states */
    if (udev->state == USB_STATE_NOTATTACHED || !is_active(intf))
        goto done;

    /* This can happen; see usb_driver_release_interface() */
    if (intf->condition == USB_INTERFACE_UNBOUND)
        goto done;
    driver = to_usb_driver(intf->dev.driver);

    if (driver->suspend) {
        status = driver->suspend(intf, msg);
        if (status == 0)
            mark_quiesced(intf);
        else if (!(msg.event & PM_EVENT_AUTO))
            dev_err(&intf->dev, "%s error %d/n",
                    "suspend", status);
    } else {
        /* Later we will unbind the driver and reprobe */
        intf->needs_binding = 1;
        dev_warn(&intf->dev, "no %s for driver %s?/n",
                "suspend", driver->name);
        mark_quiesced(intf);
    }

 done:
    dev_vdbg(&intf->dev, "%s: status %d/n", __func__, status);
    return status;
}








   































内容概要:本文围绕可变桨叶四旋翼无人机的规范控制与点对点运动模拟展开,重点研究优化推力分配策略在翻转动作中的应用与性能比较。通过Matlab代码实现,构建了四旋翼动力学模型,并设计了多种控制算法以实现精确的姿态调整与轨迹跟踪。研究对比了不同推力分配方案在执行高机动性翻转动作时的稳定性、能耗效率与响应速度,旨在提升无人机在复杂飞行任务中的动态性能与控制精度。该仿真研究为无人机飞控系统的设计与优化提供了理论依据和技术支持。; 适合人群:具备一定自动控制理论基础和Matlab编程能力,从事无人机控制、飞行器动力学或机器人系统研究的科研人员及研究生。; 使用场景及目标:① 实现四旋翼无人机在三维空间中的精确点对点运动控制;② 对比分析不同推力分配策略在执行翻转等高难度动作时的控制效果与能耗表现,优化飞行性能;③ 为无人机自主飞行、特技飞行及复杂环境下的机动控制提供算法验证平台。; 阅读建议:此资源以Matlab仿真为核心,建议读者结合相关控制理论知识,深入理解代码实现细节,重点关注动力学建模、控制律设计与推力分配模块。在学习过程中,应动手调试参数,复现文中翻转动作的仿真结果,并尝试拓展至其他复杂飞行任务,以加深对无人机控制机理的理解。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值