__devexit_p的功能

本文解析了Linux内核中的__devexit_p宏的作用及其实现原理,详细介绍了该宏如何根据条件决定是否在设备移除时调用指定的函数。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

static struct platform_driver xx_driver = {
	.driver	= {
		.name    = "xxx",
		.owner	 = THIS_MODULE,
		.pm	 = &xxx_drv_pm_ops,
	},
	.probe   = xxx_probe,
	.remove  = __devexit_p(xxx_drv_remove),
};

其中,.remove一般都是直接等于函数名,如.remove = xxx_drv_remove,内核驱动中很多也用如上的形式。

__devexit_p定义如下:

#if defined(MODULE) || defined(CONFIG_HOTPLUG)
#define __devexit_p(x) x
#else
#define __devexit_p(x) NULL
#endif

那么

.remove  = __devexit_p(xxx_drv_remove),

就等价于:

#if defined(MODULE) || defined(CONFIG_HOTPLUG)
.remove  = xxx_drv_remove,
#else
.remove  =  NULL,
#endif

总结:__devexit_p的作用其实相当于加了一个开关,当符合条件时,才会在remove时执行xxx_drv_remove函数,否则是空。

要在Linux内核中实现一个PWM驱动程序并将其与GPIO关联起来,首先需要理解基本流程,包括创建驱动、配置设备树、初始化定时器和设置GPIO功能。以下是一个简化版的概述: 1. **创建驱动**: - 创建一个新的内核模块,例如`my_pwm_driver.c`和`my_pwm_driver.ko`。在`my_pwm_driver.c`中,定义`struct pwm_device`结构体,它将包含PWM设备的数据。 ```c struct pwm_device { struct device dev; struct timer_list timer; u32 duty_cycle; }; ``` 2. **设备树配置**: - 在`drivers/pwm/Kconfig`文件中添加PWM相关的Kconfig选项,并在`Documentation/devicetree/bindings/pwm`目录下创建相应的device tree binding(dtb)文件描述PWM设备的属性。 ```dts &pwm-controller { compatible = "my_pwm_controller"; pwm-channels = <4>; pwm-frequency = <50000>; #address-cells = <1>; #size-cells = <0>; pwm-channel@0 { pinctrl-names = "default"; pinctrl-0 = <&gpio_pinctrl>; gpio = <&gpio0 0 GPIO_ACTIVE_HIGH>; }; }; ``` 3. **初始化定时器**: - 使用`timer_init()`函数在driver初始化时设置定时器,设置周期和回调函数来更新PWM的占空比。 ```c static void pwm_timer_fn(unsigned long data) { struct pwm_device *pwm_dev = (struct pwm_device *)data; pwm_dev->duty_cycle++; } int __init my_pwm_driver_init(void) { // 初始化设备 pwm_dev = kmalloc(sizeof(*pwm_dev), GFP_KERNEL); if (!pwm_dev) return -ENOMEM; // 初始化定时器 timer_init(&pwm_dev->timer, pwm_timer_fn, (unsigned long)pwm_dev); timer_start(&pwm_dev->timer, 1000 / PWM_FREQUENCY, HZ); } ``` 4. **设置GPIO功能**: - 在`driver_entry`函数中,注册GPIO并设置其功能为PWM输出。 ```c static int __devinit my_pwm_probe(struct platform_device *pdev) { // Register with the system and get GPIO pin information gpio_request(pwm_dev->gpio, "PWM Pin"); gpio_direction_output(pwm_dev->gpio, 0); // ...其他初始化操作... return 0; } static void __devexit my_pwm_remove(struct platform_device *pdev) { gpio_free(pwm_dev->gpio); } ``` 5. **用户空间接口**: - 如果需要,可以提供sysfs接口让用户空间调整PWM参数。 ```c static ssize_t duty_cycle_show(struct device *dev, struct device_attribute *attr, char *buf) { struct pwm_device *pwm_dev = container_of(dev, struct pwm_device, dev); return sprintf(buf, "%u\n", pwm_dev->duty_cycle); } static ssize_t duty_cycle_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { // Update PWM duty cycle ... return count; } static DEVICE_ATTR(duty_cycle, S_IRUGO | S_IWUSR, duty_cycle_show, duty_cycle_store); ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值