首页 | 新闻 | 新品 | 文库 | 方案 | 视频 | 下载 | 商城 | 开发板 | 数据中心 | 座谈新版 | 培训 | 工具 | 博客 | 论坛 | 百科 | GEC | 活动 | 主题月 | 电子展
返回列表 回复 发帖

Timed GPIO驱动程序分析(3)

Timed GPIO驱动程序分析(3)

timed_gpio探测函数

static int timed_gpio_probe(struct platform_device *pdev)

{

        struct timed_gpio_platform_data *pdata = pdev->dev.platform_data;

        struct timed_gpio *cur_gpio;

        struct timed_gpio_data *gpio_data, *gpio_dat;

        int i, j, ret = 0;

        if (!pdata)

                return -EBUSY; //pdata->num_gpios个GPIO分配内存空间

        gpio_data = kzalloc(sizeof(struct timed_gpio_data) * pdata->num_gpios,

                        GFP_KERNEL);

        if (!gpio_data)

                return -ENOMEM;

        for (i = 0; i < pdata->num_gpios; i++) {

                cur_gpio = &pdata->gpios;

                gpio_dat = &gpio_data;

                hrtimer_init(&gpio_dat->timer, CLOCK_MONOTONIC,//初始化定时器

                                HRTIMER_MODE_REL);

                gpio_dat->timer.function = gpio_timer_func;//定时器回调函数

                spin_lock_init(&gpio_dat->lock);

                gpio_dat->dev.name = cur_gpio->name;

                gpio_dat->dev.get_time = gpio_get_time;

                gpio_dat->dev.enable = gpio_enable;

                ret = gpio_request(cur_gpio->gpio, cur_gpio->name);//申请GPIO

                if (ret >= 0) {

                        ret = timed_output_dev_register(&gpio_dat->dev);//调用timed_output框架注册函数

                        if (ret < 0)

                                gpio_free(cur_gpio->gpio);

                }

                if (ret < 0) {

                        for (j = 0; j < i; j++) {

                                timed_output_dev_unregister(&gpio_data.dev);

                                gpio_free(gpio_data.gpio);

                        }

                        kfree(gpio_data);

                        return ret;

                }

                gpio_dat->gpio = cur_gpio->gpio;

                gpio_dat->max_timeout = cur_gpio->max_timeout;

                gpio_dat->active_low = cur_gpio->active_low;

                gpio_direction_output(gpio_dat->gpio, gpio_dat->active_low);//初始化GPIO的输出值

        }

        platform_set_drvdata(pdev, gpio_data);

        return 0;

}

初始化过程:

1. 首先调用kzalloc函数为 GPIO分配内存空间

2. 调用hrtimer_init函数初始化化内核定时器

3. 设置GPIOenable函数为gpio_enable

4. 设置GPIOget_time函数为gpio_get_time

5. 调用timed_output_dev_register函数注册设备驱动。

6. 初始化timed_gpio_data结构体

7. 调用gpio_direction_output函数设置GPIO的初始值。

GPIO驱动移除函数,调用timed_output_dev_unregister卸载驱动程序

static int timed_gpio_remove(struct platform_device *pdev)

{

        struct timed_gpio_platform_data *pdata = pdev->dev.platform_data;

        struct timed_gpio_data *gpio_data = platform_get_drvdata(pdev);

        int i;

        for (i = 0; i < pdata->num_gpios; i++) {

                timed_output_dev_unregister(&gpio_data.dev);

                gpio_free(gpio_data.gpio);

        }

        kfree(gpio_data);

        return 0;

}

功能回调函数gpio_timer_func分析:定时器超时后将执行此函数,此函数根据active_low的值来设置GPIO的高低电平。

static enum hrtimer_restart gpio_timer_func(struct hrtimer *timer)

{

        struct timed_gpio_data *data =

                container_of(timer, struct timed_gpio_data, timer);

        gpio_direction_output(data->gpio, data->active_low ? 1 : 0);

        return HRTIMER_NORESTART;

}

gpio_enable函数为关键函数接受用户空间传过来的value值用于在一定时间里控制GPIO

static void gpio_enable(struct timed_output_dev *dev, int value)

{

        struct timed_gpio_data        *data =

                container_of(dev, struct timed_gpio_data, dev);

        unsigned long        flags;

        spin_lock_irqsave(&data->lock, flags);

        /* cancel previous timer and set GPIO according to value */

        hrtimer_cancel(&data->timer);

        gpio_direction_output(data->gpio, data->active_low ? !value : !!value);

        if (value > 0) {

                if (value > data->max_timeout)

                        value = data->max_timeout;

       //启动定时器函数

                hrtimer_start(&data->timer,

                        ktime_set(value / 1000, (value % 1000) * 1000000),

                        HRTIMER_MODE_REL);

        }

        spin_unlock_irqrestore(&data->lock, flags);

}

继承事业,薪火相传
返回列表