__devexit_p的功能

__devexit_p的功能

在看i2c驱动的时候,看到有如下代码:
.remove     = __devexit_p(i2c_gpio_remove),

这里的__devexit_p有什么作用呢?
include/linux/init.h中找到了它的定义:

/* Functions marked as __devexit may be discarded at kernel link time, depending
   on config options.  Newer versions of binutils detect references from
   retained sections to discarded sections and flag an error.  Pointers to
   __devexit functions must use __devexit_p(function_name), the wrapper will
   insert either the function_name or NULL, depending on the config options.
 */

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

 

意义是内核可能在不支持模块且不支持热插拔的时候,需要对 __devexit_p返回NULL。

 

要在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、付费专栏及课程。

余额充值