1、
这段话摘于《设备驱动开发详解》
在使用串口核心层这个通用串口tty驱动层的接口后,一个串口驱动要完成的主要工作:
(1)、定义uart_driver、uart_ops、uart_port等结构体的实例并在适当的地方根据具体硬件和驱动的情况初始化它们,当然具体设备的驱动可以将这些结构体在新定义的xxx_uart_driver、xxx_uart_ops、xxx_uart_port之内。
(2)、在模块初始化是调用uart_register_driver和uart_add_port注册UART驱动并添加端口,在模块卸载时调用uart_unregister_driver和uart_remove_one_port以注销UART驱动并移除端口。
(3)、根据具体硬件的datasheet实现uart_ops中的成员函数,这些函数的实现成为UART驱动的主体工作。
2、s3c6410的串口驱动:
这些与上面的(1)相对应。
(1)、serial_core.c文件的作用:主要有如下结构体和实现其中的函数,供上层函数调用:
static const struct tty_operations uart_ops = {
.open = uart_open,
.close = uart_close,
.write = uart_write,
.put_char = uart_put_char,
.flush_chars = uart_flush_chars,
.write_room = uart_write_room,
.chars_in_buffer= uart_chars_in_buffer,
.flush_buffer = uart_flush_buffer,
.ioctl = uart_ioctl,
.throttle = uart_throttle,
.unthrottle = uart_unthrottle,
.send_xchar = uart_send_xchar,
.set_termios = uart_set_termios,
.set_ldisc = uart_set_ldisc,
.stop = uart_stop,
.start = uart_start,
.hangup = uart_hangup,
.break_ctl = uart_break_ctl,
.wait_until_sent= uart_wait_until_sent,
#ifdef CONFIG_PROC_FS
.read_proc = uart_read_proc,
#endif
.tiocmget = uart_tiocmget,
.tiocmset = uart_tiocmset,
#ifdef CONFIG_CONSOLE_POLL
.poll_init = uart_poll_init,
.poll_get_char= uart_poll_get_char,
.poll_put_char= uart_poll_put_char,
#endif
};
并提供uart_register_driver、uart_unregister_driver、uart_add_one_port、uart_remove_one_port函数供底层函数注册。
(2)、在sansung.c文件中有如下:
static struct uart_ops s3c24xx_serial_ops = {
.pm = s3c24xx_serial_pm,
.tx_empty = s3c24xx_serial_tx_empty,
.get_mctrl = s3c24xx_serial_get_mctrl,
.set_mctrl = s3c24xx_serial_set_mctrl,
.stop_tx = s3c24xx_serial_stop_tx,
.start_tx = s3c24xx_serial_start_tx,
.stop_rx = s3c24xx_serial_stop_rx,
.enable_ms = s3c24xx_serial_enable_ms,
.break_ctl = s3c24xx_serial_break_ctl,
.startup = s3c24xx_serial_startup,
.shutdown = s3c24xx_serial_shutdown,
.set_termios = s3c24xx_serial_set_termios,
.type = s3c24xx_serial_type,
.release_port = s3c24xx_serial_release_port,
.request_port = s3c24xx_serial_request_port,
.config_port = s3c24xx_serial_config_port,
.verify_port = s3c24xx_serial_verify_port,
};
static struct uart_drivers3c24xx_uart_drv = {
.owner = THIS_MODULE,
.dev_name = "s3c2410_serial",
.nr = CONFIG_SERIAL_SAMSUNG_UARTS,
.cons = S3C24XX_SERIAL_CONSOLE,
.driver_name = S3C24XX_SERIAL_NAME,
.major = S3C24XX_SERIAL_MAJOR,
.minor = S3C24XX_SERIAL_MINOR,
};
原始结构为
struct uart_driver {
struct module *owner;
const char *driver_name;
const char *dev_name;
int major;
int minor;
int nr;
struct console *cons;
/*
* these are private; the low level driver should not
* touch these; they should be initialised to NULL
*/
struct uart_state *state;
struct tty_driver *tty_driver;
};
static struct s3c24xx_uart_port s3c24xx_serial_ports[CONFIG_SERIAL_SAMSUNG_UARTS] = {
[0] = {
.port = {
.lock = __SPIN_LOCK_UNLOCKED(s3c24xx_serial_ports[0].port.lock),
.iotype = UPIO_MEM,
.irq = IRQ_S3CUART_RX0,
.uartclk = 0,
.fifosize = 16,
.ops = &s3c24xx_serial_ops,
.flags = UPF_BOOT_AUTOCONF,
.line = 0,
}
},
[1] = {
.port = {
.lock = __SPIN_LOCK_UNLOCKED(s3c24xx_serial_ports[1].port.lock),
.iotype = UPIO_MEM,
.irq = IRQ_S3CUART_RX1,
.uartclk = 0,
.fifosize = 16,
.ops = &s3c24xx_serial_ops,
.flags = UPF_BOOT_AUTOCONF,
.line = 1,
}
},
#if CONFIG_SERIAL_SAMSUNG_UARTS > 2
[2] = {
.port = {
.lock = __SPIN_LOCK_UNLOCKED(s3c24xx_serial_ports[2].port.lock),
.iotype = UPIO_MEM,
.irq = IRQ_S3CUART_RX2,
.uartclk = 0,
.fifosize = 16,
.ops = &s3c24xx_serial_ops,
.flags = UPF_BOOT_AUTOCONF,
.line = 2,
}
},
#endif
#if CONFIG_SERIAL_SAMSUNG_UARTS > 3
[3] = {
.port = {
.lock = __SPIN_LOCK_UNLOCKED(s3c24xx_serial_ports[3].port.lock),
.iotype = UPIO_MEM,
.irq = IRQ_S3CUART_RX3,
.uartclk = 0,
.fifosize = 16,
.ops = &s3c24xx_serial_ops,
//---->modify by phantom
#if 1
.flags = UPF_BOOT_AUTOCONF | UPF_CONS_FLOW,
#else
.flags = UPF_BOOT_AUTOCONF,
#endif
//<----
.line = 3,
}
}
#endif
};
这个数组中的内容其实就是对下面struct uart_port结构成员的初始化。
其中: 结构体s3c24xx_uart_port源码如下:
struct s3c24xx_uart_port {
unsigned charrx_claimed;
unsigned chartx_claimed;
unsigned intpm_level;
unsigned longbaudclk_rate;
unsigned intrx_irq;
unsigned inttx_irq;
struct s3c24xx_uart_info*info;
struct s3c24xx_uart_clksrc*clksrc;
struct clk*clk;
struct clk*baudclk;
struct uart_portport;
#ifdef CONFIG_CPU_FREQ
struct notifier_blockfreq_transition;
#endif
};
其中:struct uart_port源码如下:
struct uart_port {
spinlock_tlock;/* port lock */
unsigned long iobase; /* in/out[bwl] */
unsigned char __iomem*membase;/* read/write[bwl] */
unsigned int irq; /* irq number */
unsigned intuartclk;/* base uart clock */
unsigned intfifosize;/* tx fifo size */
unsigned charx_char;/* xon/xoff char */
unsigned charregshift;/* reg offset shift */
unsigned chariotype;/* io access style */
unsigned charunused1;
#define UPIO_PORT(0)
#define UPIO_HUB6(1)
#define UPIO_MEM(2)
#define UPIO_MEM32(3)
#define UPIO_AU(4)/* Au1x00 type IO */
#define UPIO_TSI(5)/* Tsi108/109 type IO */
#define UPIO_DWAPB(6)/* DesignWare APB UART */
#define UPIO_RM9000(7)/* RM9000 type IO */
unsigned intread_status_mask;/* driver specific */
unsigned intignore_status_mask;/* driver specific */
struct uart_info*info;/* pointer to parent info */
struct uart_icounticount;/* statistics */
struct console*cons;/* struct console, if any */
#ifdef CONFIG_SERIAL_CORE_CONSOLE
unsigned longsysrq;/* sysrq timeout */
#endif
upf_tflags;
#define UPF_FOURPORT((__force upf_t) (1 << 1))
#define UPF_SAK((__force upf_t) (1 << 2))
#define UPF_SPD_MASK((__force upf_t) (0x1030))
#define UPF_SPD_HI((__force upf_t) (0x0010))
#define UPF_SPD_VHI((__force upf_t) (0x0020))
#define UPF_SPD_CUST((__force upf_t) (0x0030))
#define UPF_SPD_SHI((__force upf_t) (0x1000))
#define UPF_SPD_WARP((__force upf_t) (0x1010))
#define UPF_SKIP_TEST((__force upf_t) (1 << 6))
#define UPF_AUTO_IRQ((__force upf_t) (1 << 7))
#define UPF_HARDPPS_CD((__force upf_t) (1 << 11))
#define UPF_LOW_LATENCY((__force upf_t) (1 << 13))
#define UPF_BUGGY_UART((__force upf_t) (1 << 14))
#define UPF_MAGIC_MULTIPLIER((__force upf_t) (1 << 16))
#define UPF_CONS_FLOW((__force upf_t) (1 << 23))
#define UPF_SHARE_IRQ((__force upf_t) (1 << 24))
#define UPF_BOOT_AUTOCONF((__force upf_t) (1 << 28))
#define UPF_FIXED_PORT((__force upf_t) (1 << 29))
#define UPF_DEAD((__force upf_t) (1 << 30))
#define UPF_IOREMAP((__force upf_t) (1 << 31))
#define UPF_CHANGE_MASK((__force upf_t) (0x17fff))
#define UPF_USR_MASK((__force upf_t) (UPF_SPD_MASK|UPF_LOW_LATENCY))
unsigned intmctrl;/* current modem ctrl settings */
unsigned inttimeout;/* character-based timeout */
unsigned inttype;/* port type */
const struct uart_ops*ops;
unsigned intcustom_divisor;
unsigned intline;/* port index */
resource_size_tmapbase;/* for ioremap */
struct device*dev;/* parent device */
unsigned charhub6;/* this should be in the 8250 driver */
unsigned charsuspended;
unsigned charunused[2];
void*private_data;/* generic platform data pointer */
};
上一篇:ARM9 2410移植之ARM中断原理, 中断嵌套的误区,中断号的怎么来的
下一篇:linux中触摸屏驱动的实现(2)——基于s3c6410处理器
推荐阅读最新更新时间:2024-11-11 12:02
设计资源 培训 开发板 精华推荐
- LT1963A 系列的典型应用 - 1.5A、低噪声、快速瞬态响应 LDO 稳压器
- 【课程设计】桌面小音响-D类功放
- 2 相、双输出同步升压转换器使用 LTC1871 解决严酷环境中的热问题,2 相、双输出同步升压转换器解决严酷环境中的热问题
- 天气桌面站。
- 具有低漂移满量程微调的 LT1021BCH-5 CMOS DAC 基准的典型应用
- LTC1980,单节锂离子电池的典型应用
- SY58607U,用于 GB 以太网交换机的时钟缓冲器的评估板
- LTM4603HVEV 演示板、可同步 28V、6A 降压模块稳压器
- AM2G-2405SH30Z 5V 2 瓦 DC-DC 转换器的典型应用
- 具有电源正常输出的 LTC1728ES5-5、3.3V 和 5V 三路电源监视器的典型应用