linux kernel min_t
时间: 2024-06-21 10:02:07 浏览: 4
min_t 是 Linux 内核中的一个宏定义,用于比较两个值的大小并返回其中较小的那个。它的定义如下:
```
#define min_t(type, x, y) ({ \
type __min1 = (x); \
type __min2 = (y); \
__min1 < __min2 ? __min1: __min2; })
```
其中,type 表示待比较的数据类型,x 和 y 分别表示要比较的两个值。
使用 min_t 宏定义可以使代码更加简洁和易读。举个例子,如果要比较两个整数 a 和 b 的大小,并返回其中较小的那个,可以这样写:
```
int a = 10;
int b = 20;
int c = min_t(int, a, b);
```
在上面的代码中,c 的值为 a 和 b 中的较小值,即 10。
相关问题
解读linux3.4内核文件serial_core.c的代码
serial_core.c是Linux内核中的一个串口驱动核心文件,主要负责串口设备的初始化、读写和中断处理等操作。以下是该文件的代码解读:
1. 头文件包含
```
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/device.h>
#include <linux/init.h>
#include <linux/serial.h>
#include <linux/tty.h>
#include <linux/tty_flip.h>
#include <linux/console.h>
#include <linux/console_struct.h>
#include <linux/serial_core.h>
#include <linux/serial_reg.h>
#include <linux/io.h>
#include <linux/spinlock.h>
#include <linux/interrupt.h>
#include <linux/wait.h>
#include <linux/dmaengine.h>
#include <linux/dma-mapping.h>
```
该文件包含了一些常用的头文件,如内核头文件、串口头文件、中断头文件等。
2. 宏定义
```
#define serial_outp(port, value) writeb((value), (port))
#define serial_inp(port) readb(port)
#define serial_outw(port, value) writew((value), (port))
#define serial_inw(port) readw(port)
#define serial_outl(port, value) writel((value), (port))
#define serial_inl(port) readl(port)
```
这些宏定义了读写串口寄存器的操作,通过调用内核提供的读写函数实现。
3. 结构体定义
```
struct uart_port {
spinlock_t lock; /* 锁 */
void __iomem *membase; /* MMIO基地址 */
unsigned char *mapbase; /* 端口映射基地址 */
unsigned char *membase_addr; /* MMIO地址 */
unsigned char *mapbase_addr; /* 端口映射地址 */
unsigned int iotype:2; /* 端口类型 */
unsigned int irq; /* 中断号 */
unsigned int uartclk; /* 时钟 */
unsigned int fifosize; /* FIFO大小 */
unsigned int flags; /* 标志 */
unsigned int regshift; /* 寄存器位移 */
unsigned int iobase; /* 端口基地址 */
unsigned int iolen; /* 端口长度 */
unsigned int regtype:2; /* 寄存器类型 */
unsigned int uartclk_high; /* 高位时钟 */
struct uart_state *state; /* 串口状态 */
struct uart_ops *ops; /* 串口操作 */
struct uart_driver *uartclk_reg; /* 时钟寄存器 */
struct console *cons; /* 控制台 */
struct device *dev; /* 设备 */
struct dma_chan *dma; /* DMA通道 */
struct dma_async_tx_descriptor *tx_dma; /* DMA传输描述符 */
struct dma_async_tx_descriptor *rx_dma; /* DMA传输描述符 */
unsigned int capabilities; /* 串口功能 */
unsigned int type; /* 串口类型 */
unsigned int line; /* 串口线路 */
unsigned int uartclk_rate; /* 时钟频率 */
struct ktermios *termios; /* 终端参数 */
struct ktermios *gpios; /* GPIO配置 */
struct delayed_work work; /* 延迟工作队列 */
};
```
该结构体定义了串口端口的各种信息,如锁、基地址、中断号、时钟、标志等。
4. 函数定义
该文件包含了众多函数定义,具体解读如下:
(1) uart_get_baud_rate()函数
```
unsigned int uart_get_baud_rate(struct uart_port *port, struct ktermios *termios, struct ktermios *old, unsigned int min, unsigned int max)
```
该函数用于获取波特率,根据终端参数计算波特率并返回。
(2) uart_update_timeout()函数
```
void uart_update_timeout(struct uart_port *port, unsigned int cflag)
```
该函数用于更新串口超时时间,根据终端参数计算超时时间并更新。
(3) uart_register_driver()函数
```
int uart_register_driver(struct uart_driver *uart_drv)
```
该函数用于注册串口驱动,将驱动加入到内核串口驱动链表中。
(4) uart_unregister_driver()函数
```
void uart_unregister_driver(struct uart_driver *uart_drv)
```
该函数用于注销串口驱动,从内核串口驱动链表中移除。
(5) uart_add_one_port()函数
```
int uart_add_one_port(struct uart_driver *drv, struct uart_port *port)
```
该函数用于添加一个串口端口,将其加入到驱动的端口列表中。
(6) uart_remove_one_port()函数
```
void uart_remove_one_port(struct uart_driver *drv, struct uart_port *port)
```
该函数用于移除一个串口端口,从驱动的端口列表中删除。
(7) uart_suspend_port()函数
```
int uart_suspend_port(struct uart_driver *drv, struct uart_port *port)
```
该函数用于挂起一个串口端口,暂停其读写操作。
(8) uart_resume_port()函数
```
int uart_resume_port(struct uart_driver *drv, struct uart_port *port)
```
该函数用于恢复一个串口端口,重新开始读写操作。
(9) uart_change_speed()函数
```
void uart_change_speed(struct uart_port *port, unsigned int new_speed)
```
该函数用于改变串口的波特率,重新计算超时时间。
(10) uart_handle_sysrq_char()函数
```
int uart_handle_sysrq_char(struct uart_port *port, unsigned int ch)
```
该函数用于处理系统请求字符,将其发送到串口设备中。
(11) uart_insert_char()函数
```
void uart_insert_char(struct uart_port *port, unsigned int status, unsigned int overrun, unsigned int ch, unsigned int flag)
```
该函数用于向串口设备中插入一个字符,处理溢出和错误等情况。
(12) uart_write_wakeup()函数
```
void uart_write_wakeup(struct uart_port *port)
```
该函数用于唤醒串口设备的写操作,将等待的进程唤醒。
(13) uart_flush_buffer()函数
```
void uart_flush_buffer(struct uart_port *port)
```
该函数用于刷新串口设备的缓冲区,清空缓冲区中的数据。
(14) uart_start()函数
```
void uart_start(struct uart_port *port)
```
该函数用于启动串口设备的读操作,开始接收数据。
(15) uart_stop()函数
```
void uart_stop(struct uart_port *port)
```
该函数用于停止串口设备的读操作,停止接收数据。
(16) uart_shutdown()函数
```
void uart_shutdown(struct uart_port *port)
```
该函数用于关闭串口设备,释放资源。
(17) uart_handle_cts_change()函数
```
void uart_handle_cts_change(struct uart_port *port, unsigned int status)
```
该函数用于处理CTS(清除发送)信号的变化,控制发送操作。
(18) uart_handle_dcd_change()函数
```
void uart_handle_dcd_change(struct uart_port *port, unsigned int status)
```
该函数用于处理DCD(数据载波检测)信号的变化,控制读操作。
(19) uart_handle_dsr_change()函数
```
void uart_handle_dsr_change(struct uart_port *port, unsigned int status)
```
该函数用于处理DSR(数据终端就绪)信号的变化,控制读操作。
(20) uart_get_stats()函数
```
void uart_get_stats(struct uart_port *port, struct uart_icount *icount)
```
该函数用于获取串口设备的统计信息,包括接收、发送、错误等信息。
5. 总结
serial_core.c是Linux内核中的一个串口驱动核心文件,包含了众多的函数和结构体定义,实现了串口设备的初始化、读写、中断处理等操作。对于Linux内核开发人员来说,了解该文件的代码实现,对于理解串口驱动的原理和实现具有重要意义。
kernel RS232 触摸屏 驱动代码
以下是一个简单的Linux内核RS232触摸屏驱动代码的示例,用于演示输入子系统的实现方法:
```
#include <linux/module.h>
#include <linux/init.h>
#include <linux/serial.h>
#include <linux/input.h>
#define TOUCHSCREEN_NAME "rs232_touchscreen"
#define TOUCHSCREEN_MIN_X 0
#define TOUCHSCREEN_MAX_X 1023
#define TOUCHSCREEN_MIN_Y 0
#define TOUCHSCREEN_MAX_Y 767
static struct input_dev *ts_input_dev;
static struct serio *ts_serio;
static irqreturn_t ts_interrupt(int irq, void *dev_id)
{
u8 buf[3];
int x, y;
serio_read(ts_serio, buf, sizeof(buf));
/* 解析串口数据,获取坐标信息 */
x = buf[0] | ((buf[1] & 0x0F) << 8);
y = buf[2] | ((buf[1] & 0xF0) << 4);
/* 转换坐标系 */
x = TOUCHSCREEN_MIN_X + x * (TOUCHSCREEN_MAX_X - TOUCHSCREEN_MIN_X) / 0xFFF;
y = TOUCHSCREEN_MIN_Y + y * (TOUCHSCREEN_MAX_Y - TOUCHSCREEN_MIN_Y) / 0xFFF;
/* 向输入子系统报告事件 */
input_report_abs(ts_input_dev, ABS_X, x);
input_report_abs(ts_input_dev, ABS_Y, y);
input_report_key(ts_input_dev, BTN_TOUCH, 1);
input_sync(ts_input_dev);
return IRQ_HANDLED;
}
static int ts_probe(struct serio *serio, struct serio_driver *drv)
{
int err;
/* 分配输入设备结构体 */
ts_input_dev = input_allocate_device();
if (!ts_input_dev)
return -ENOMEM;
/* 设置输入设备参数 */
ts_input_dev->name = TOUCHSCREEN_NAME;
ts_input_dev->id.bustype = BUS_RS232;
ts_input_dev->evbit[0] = BIT_MASK(EV_ABS) | BIT_MASK(EV_KEY);
ts_input_dev->absbit[0] = BIT_MASK(ABS_X) | BIT_MASK(ABS_Y);
ts_input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
/* 注册输入设备 */
err = input_register_device(ts_input_dev);
if (err) {
input_free_device(ts_input_dev);
return err;
}
/* 记录串口设备 */
ts_serio = serio;
/* 注册中断 */
err = serio_open(ts_serio, drv);
if (err) {
input_unregister_device(ts_input_dev);
return err;
}
err = request_irq(ts_serio->irq, ts_interrupt, IRQF_SHARED, TOUCHSCREEN_NAME, ts_serio);
if (err) {
serio_close(ts_serio);
input_unregister_device(ts_input_dev);
return err;
}
return 0;
}
static void ts_disconnect(struct serio *serio)
{
/* 释放中断和串口 */
free_irq(serio->irq, serio);
serio_close(serio);
/* 注销输入设备 */
input_unregister_device(ts_input_dev);
input_free_device(ts_input_dev);
}
static const struct serio_device_id ts_serio_ids[] = {
{
.type = SERIO_RS232,
.proto = SERIO_RS232,
.id = SERIO_ANY_ID,
.description = "RS232 Touchscreen",
},
{ }
};
MODULE_DEVICE_TABLE(serio, ts_serio_ids);
static struct serio_driver ts_drv = {
.driver = {
.name = "rs232_touchscreen",
.owner = THIS_MODULE,
},
.id_table = ts_serio_ids,
.probe = ts_probe,
.disconnect = ts_disconnect,
};
static int __init ts_init(void)
{
return serio_register_driver(&ts_drv);
}
static void __exit ts_exit(void)
{
serio_unregister_driver(&ts_drv);
}
module_init(ts_init);
module_exit(ts_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Your Name <youremail@example.com>");
MODULE_DESCRIPTION("RS232 Touchscreen Driver");
```
以上代码中,驱动程序使用了输入子系统的API来报告触摸事件,并且通过解析串口数据来获取坐标信息。需要注意的是,不同的触摸屏硬件设备可能存在一些细节上的差异,因此需要仔细查阅硬件文档来进行相应的调整和修改。