常用内核接口:
1、request_threaded_irq
1 int request_threaded_irq(unsigned int irq, irq_handler_t handler, irq_handler_t thread_fn,unsigned long irqflags, const char *devname, void *dev_id)
其中,irq是中断号, handler是在发生中断时,首先要执行的code,非常类似于顶半,该函数最后会return IRQ_WAKE_THREAD来唤醒中断线程,一般设为NULL,用系统提供的默认处理。thread_fn,是要在线程里执行的handler,非常类似于底半。 后三个参数基本和request_irq相同。irqsflags新增加了一个标志,IRQF_ONESHOT,用来标明是在中断线程执行完后在打开该中断,该标志非常有用,否则中断有可能一直在顶半执行,而不能处理中断线程。
2、int request_threaded_irq(unsigned int irq, irq_handler_t handler, irq_handler_t thread_fn,unsigned long irqflags, const char *devname, void *dev_id)
1 #define container_of(ptr, type, member) ({ 2 const typeof( ((type *)0)->member ) *__mptr = (ptr); 3 (type *)( (char *)__mptr - offsetof(type,member) );
})
其中,1)判断ptr 与 member 是否为同意类型
2)计算size大小,结构体的起始地址 = (type *)((char *)ptr - size) (注:强转为该结构体指针)
现在我们知道container_of()的作用就是通过一个结构变量中一个成员的地址找到这个结构体变量的首地址。
container_of(ptr,type,member),这里面有ptr,type,member分别代表指针、类型、成员。
3、MODULE_DEVICE_TABLE
1 static struct spi_device_id nanohub_spi_id[] = { 2 {NANOHUB_NAME, 0}, 3 4 {}, 5 6 }; 7 8 MODULE_DEVICE_TABLE(spi, nanohub_spi_id);
1 //MODULE_DEVICE_TABLE宏的定义如下: 2 3 #define MODULE_DEVICE_TABLE(type, name) 4 5 extern const struct type##_device_id __mod_##type##__##name##_device_table 6 __attribute__ ((unused, alias(__stringify(name))))
MODULE_DEVICE_TABLE一般用在热插拔的设备驱动中(例如:IIC、SPI)。
上述xx_driver_ids结构,是此驱动所支持的设备列表。
作用是:将xx_driver_ids结构输出到用户空间,这样模块加载系统在加载模块时,就知道了什么模块对应什么硬件设备。
用法是:MODULE_DEVICE_TABLE(设备类型,设备表),其中,设备类型,包括USB,PCI等,也可以自己起名字,上述代码中是针对不同的平台分的类;设备表也是自己定义的,它的最后一项必须是空,用来标识结束。
(转载自:https://blog.csdn.net/u012308586/article/details/90750720)
(转载自:https://blog.csdn.net/s2603898260/article/details/79371024)