tiny4412 串口驱动分析五 --- LDD3上TTY驱动程序源码
关于tty这部分请参考:
《Linux设备驱动开发详解 第二版》第14章 Linux终端设备驱动
《精通Linux设备驱动程序开发》第6章 串行设备驱动程序
《Linux设备驱动程序 第三版》第18章 TTY驱动程序
下面是一些串口相关的文档:
http://pan.baidu.com/s/1mg20Umc
Makefile:
# Comment/uncomment the following line to disable/enable debugging #DEBUG = y# Add your debugging flag (or not) to CFLAGS ifeq ($(DEBUG),y)DEBFLAGS = -O -g -DSCULL_DEBUG # "-O" is needed to expand inlines elseDEBFLAGS = -O2 endifEXTRA_CFLAGS += $(DEBFLAGS) EXTRA_CFLAGS += -I..ifneq ($(KERNELRELEASE),) # call from kernel build systemobj-m := tiny_tty.o tiny_serial.oelse#KERNELDIR ?= /lib/modules/$(shell uname -r)/build KERNELDIR ?= /root/Tiny4412_android_4_1_2/linux-3.0.31 PWD := $(shell pwd)default:$(MAKE) -C $(KERNELDIR) M=$(PWD) modulesendifclean:rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versionsdepend .depend dep:$(CC) $(EXTRA_CFLAGS) -M *.c > .dependifeq (.depend,$(wildcard .depend)) include .depend endif
tiny_tty.c
/** Tiny TTY driver** Copyright (C) 2002-2004 Greg Kroah-Hartman (greg@kroah.com)** This program is free software; you can redistribute it and/or modify* it under the terms of the GNU General Public License as published by* the Free Software Foundation, version 2 of the License.** This driver shows how to create a minimal tty driver. It does not rely on* any backing hardware, but creates a timer that emulates data being received* from some kind of hardware.*/#include <linux/kernel.h> #include <linux/errno.h> #include <linux/init.h> #include <linux/module.h> #include <linux/slab.h> #include <linux/wait.h> #include <linux/tty.h> #include <linux/tty_driver.h> #include <linux/tty_flip.h> #include <linux/serial.h> #include <linux/sched.h> #include <linux/seq_file.h> #include <asm/uaccess.h>#define DRIVER_VERSION "v2.0" #define DRIVER_AUTHOR "Greg Kroah-Hartman <greg@kroah.com>" #define DRIVER_DESC "Tiny TTY driver"/* Module information */ MODULE_AUTHOR( DRIVER_AUTHOR ); MODULE_DESCRIPTION( DRIVER_DESC ); MODULE_LICENSE("GPL");#define DELAY_TIME HZ * 2 /* 2 seconds per character */ #define TINY_DATA_CHARACTER 't'#define TINY_TTY_MAJOR 240 /* experimental range */ #define TINY_TTY_MINORS 4 /* only have 4 devices */struct tiny_serial {struct tty_struct *tty; /* pointer to the tty for this device */int open_count; /* number of times this port has been opened */struct semaphore sem; /* locks this structure */struct timer_list *timer;/* for tiocmget and tiocmset functions */int msr; /* MSR shadow */int mcr; /* MCR shadow *//* for ioctl fun */struct serial_struct serial;wait_queue_head_t wait;struct async_icount icount; };static struct tiny_serial *tiny_table[TINY_TTY_MINORS]; /* initially all NULL */static void tiny_timer(unsigned long timer_data) {struct tiny_serial *tiny = (struct tiny_serial *)timer_data;struct tty_struct *tty;int i;char data[1] = {TINY_DATA_CHARACTER};int data_size = 1;if (!tiny)return;tty = tiny->tty;/* send the data to the tty layer for users to read. This doesn't* actually push the data through unless tty->low_latency is set */for (i = 0; i < data_size; ++i) {if (!tty_buffer_request_room(tty, 1))tty_flip_buffer_push(tty);tty_insert_flip_char(tty, data[i], TTY_NORMAL);}tty_flip_buffer_push(tty);/* resubmit the timer again */tiny->timer->expires = jiffies + DELAY_TIME;add_timer(tiny->timer); }static int tiny_open(struct tty_struct *tty, struct file *file) {struct tiny_serial *tiny;struct timer_list *timer;int index;/* initialize the pointer in case something fails */tty->driver_data = NULL;/* get the serial object associated with this tty pointer */index = tty->index;tiny = tiny_table[index];if (tiny == NULL) {/* first time accessing this device, let's create it */tiny = kmalloc(sizeof(*tiny), GFP_KERNEL);if (!tiny)return -ENOMEM;sema_init(&tiny->sem, 1);tiny->open_count = 0;tiny->timer = NULL;tiny_table[index] = tiny;}down(&tiny->sem);/* save our structure within the tty structure */tty->driver_data = tiny;tiny->tty = tty;++tiny->open_count;if (tiny->open_count == 1) {/* this is the first time this port is opened *//* do any hardware initialization needed here *//* create our timer and submit it */if (!tiny->timer) {timer = kmalloc(sizeof(*timer), GFP_KERNEL);if (!timer) {up(&tiny->sem);return -ENOMEM;}tiny->timer = timer;}init_timer(tiny->timer);tiny->timer->data = (unsigned long )tiny;tiny->timer->expires = jiffies + DELAY_TIME;tiny->timer->function = tiny_timer;add_timer(tiny->timer);}up(&tiny->sem);return 0; }static void do_close(struct tiny_serial *tiny) {down(&tiny->sem);if (!tiny->open_count) {/* port was never opened */goto exit;}--tiny->open_count;if (tiny->open_count <= 0) {/* The port is being closed by the last user. *//* Do any hardware specific stuff here *//* shut down our timer */del_timer(tiny->timer);} exit:up(&tiny->sem); }static void tiny_close(struct tty_struct *tty, struct file *file) {struct tiny_serial *tiny = tty->driver_data;if (tiny)do_close(tiny); } static int tiny_write(struct tty_struct *tty, const unsigned char *buffer, int count) {struct tiny_serial *tiny = tty->driver_data;int i;int retval = -EINVAL;if (!tiny)return -ENODEV;down(&tiny->sem);if (!tiny->open_count)/* port was not opened */goto exit;/* fake sending the data out a hardware port by* writing it to the kernel debug log.*/printk(KERN_DEBUG "%s - ", __FUNCTION__);for (i = 0; i < count; ++i)printk("%02x ", buffer[i]);printk("\n");exit:up(&tiny->sem);return retval; }static int tiny_write_room(struct tty_struct *tty) {struct tiny_serial *tiny = tty->driver_data;int room = -EINVAL;if (!tiny)return -ENODEV;down(&tiny->sem);if (!tiny->open_count) {/* port was not opened */goto exit;}/* calculate how much room is left in the device */room = 255;exit:up(&tiny->sem);return room; }#define RELEVANT_IFLAG(iflag) ((iflag) & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK))static void tiny_set_termios(struct tty_struct *tty, struct ktermios *old_termios) {unsigned int cflag;cflag = tty->termios->c_cflag;/* check that they really want us to change something */if (old_termios) {if ((cflag == old_termios->c_cflag) &&(RELEVANT_IFLAG(tty->termios->c_iflag) == RELEVANT_IFLAG(old_termios->c_iflag))) {printk(KERN_DEBUG " - nothing to change...\n");return;}}/* get the byte size */switch (cflag & CSIZE) {case CS5:printk(KERN_DEBUG " - data bits = 5\n");break;case CS6:printk(KERN_DEBUG " - data bits = 6\n");break;case CS7:printk(KERN_DEBUG " - data bits = 7\n");break;default:case CS8:printk(KERN_DEBUG " - data bits = 8\n");break;}/* determine the parity */if (cflag & PARENB)if (cflag & PARODD)printk(KERN_DEBUG " - parity = odd\n");elseprintk(KERN_DEBUG " - parity = even\n");elseprintk(KERN_DEBUG " - parity = none\n");/* figure out the stop bits requested */if (cflag & CSTOPB)printk(KERN_DEBUG " - stop bits = 2\n");elseprintk(KERN_DEBUG " - stop bits = 1\n");/* figure out the hardware flow control settings */if (cflag & CRTSCTS)printk(KERN_DEBUG " - RTS/CTS is enabled\n");elseprintk(KERN_DEBUG " - RTS/CTS is disabled\n");/* determine software flow control *//* if we are implementing XON/XOFF, set the start and * stop character in the device */if (I_IXOFF(tty) || I_IXON(tty)) {unsigned char stop_char = STOP_CHAR(tty);unsigned char start_char = START_CHAR(tty);/* if we are implementing INBOUND XON/XOFF */if (I_IXOFF(tty))printk(KERN_DEBUG " - INBOUND XON/XOFF is enabled, ""XON = %2x, XOFF = %2x", start_char, stop_char);elseprintk(KERN_DEBUG" - INBOUND XON/XOFF is disabled");/* if we are implementing OUTBOUND XON/XOFF */if (I_IXON(tty))printk(KERN_DEBUG" - OUTBOUND XON/XOFF is enabled, ""XON = %2x, XOFF = %2x", start_char, stop_char);elseprintk(KERN_DEBUG" - OUTBOUND XON/XOFF is disabled");}/* get the baud rate wanted */printk(KERN_DEBUG " - baud rate = %d", tty_get_baud_rate(tty)); }/* Our fake UART values */ #define MCR_DTR 0x01 #define MCR_RTS 0x02 #define MCR_LOOP 0x04 #define MSR_CTS 0x08 #define MSR_CD 0x10 #define MSR_RI 0x20 #define MSR_DSR 0x40static int tiny_tiocmget(struct tty_struct *tty) {struct tiny_serial *tiny = tty->driver_data;unsigned int result = 0;unsigned int msr = tiny->msr;unsigned int mcr = tiny->mcr;result = ((mcr & MCR_DTR) ? TIOCM_DTR : 0) | /* DTR is set */((mcr & MCR_RTS) ? TIOCM_RTS : 0) | /* RTS is set */((mcr & MCR_LOOP) ? TIOCM_LOOP : 0) | /* LOOP is set */((msr & MSR_CTS) ? TIOCM_CTS : 0) | /* CTS is set */((msr & MSR_CD) ? TIOCM_CAR : 0) | /* Carrier detect is set*/((msr & MSR_RI) ? TIOCM_RI : 0) | /* Ring Indicator is set */((msr & MSR_DSR) ? TIOCM_DSR : 0); /* DSR is set */return result; }static int tiny_tiocmset(struct tty_struct *tty, unsigned int set,unsigned int clear) {struct tiny_serial *tiny = tty->driver_data;unsigned int mcr = tiny->mcr;if (set & TIOCM_RTS)mcr |= MCR_RTS;if (set & TIOCM_DTR)mcr |= MCR_RTS;if (clear & TIOCM_RTS)mcr &= ~MCR_RTS;if (clear & TIOCM_DTR)mcr &= ~MCR_RTS;/* set the new MCR value in the device */tiny->mcr = mcr;return 0; }static int tiny_proc_show(struct seq_file *m, void *v) {struct tiny_serial *tiny;int i;seq_printf(m, "tinyserinfo:1.0 driver:%s\n", DRIVER_VERSION);for (i = 0; i < TINY_TTY_MINORS; ++i) {tiny = tiny_table[i];if (tiny == NULL)continue;seq_printf(m, "%d\n", i);}return 0; }#define tiny_ioctl tiny_ioctl_tiocgserial static int tiny_ioctl(struct tty_struct *tty, unsigned int cmd,unsigned long arg) {struct tiny_serial *tiny = tty->driver_data;if (cmd == TIOCGSERIAL) {struct serial_struct tmp;if (!arg)return -EFAULT;memset(&tmp, 0, sizeof(tmp));tmp.type = tiny->serial.type;tmp.line = tiny->serial.line;tmp.port = tiny->serial.port;tmp.irq = tiny->serial.irq;tmp.flags = ASYNC_SKIP_TEST | ASYNC_AUTO_IRQ;tmp.xmit_fifo_size = tiny->serial.xmit_fifo_size;tmp.baud_base = tiny->serial.baud_base;tmp.close_delay = 5*HZ;tmp.closing_wait = 30*HZ;tmp.custom_divisor = tiny->serial.custom_divisor;tmp.hub6 = tiny->serial.hub6;tmp.io_type = tiny->serial.io_type;if (copy_to_user((void __user *)arg, &tmp, sizeof(struct serial_struct)))return -EFAULT;return 0;}return -ENOIOCTLCMD; } #undef tiny_ioctl#define tiny_ioctl tiny_ioctl_tiocmiwait static int tiny_ioctl(struct tty_struct *tty, unsigned int cmd,unsigned long arg) {struct tiny_serial *tiny = tty->driver_data;if (cmd == TIOCMIWAIT) {DECLARE_WAITQUEUE(wait, current);struct async_icount cnow;struct async_icount cprev;cprev = tiny->icount;while (1) {add_wait_queue(&tiny->wait, &wait);set_current_state(TASK_INTERRUPTIBLE);schedule();remove_wait_queue(&tiny->wait, &wait);/* see if a signal woke us up */if (signal_pending(current))return -ERESTARTSYS;cnow = tiny->icount;if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr &&cnow.dcd == cprev.dcd && cnow.cts == cprev.cts)return -EIO; /* no change => error */if (((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) ||((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) ||((arg & TIOCM_CD) && (cnow.dcd != cprev.dcd)) ||((arg & TIOCM_CTS) && (cnow.cts != cprev.cts)) ) {return 0;}cprev = cnow;}}return -ENOIOCTLCMD; } #undef tiny_ioctl#define tiny_ioctl tiny_ioctl_tiocgicount static int tiny_ioctl(struct tty_struct *tty, unsigned int cmd,unsigned long arg) {struct tiny_serial *tiny = tty->driver_data;if (cmd == TIOCGICOUNT) {struct async_icount cnow = tiny->icount;struct serial_icounter_struct icount;icount.cts = cnow.cts;icount.dsr = cnow.dsr;icount.rng = cnow.rng;icount.dcd = cnow.dcd;icount.rx = cnow.rx;icount.tx = cnow.tx;icount.frame = cnow.frame;icount.overrun = cnow.overrun;icount.parity = cnow.parity;icount.brk = cnow.brk;icount.buf_overrun = cnow.buf_overrun;if (copy_to_user((void __user *)arg, &icount, sizeof(icount)))return -EFAULT;return 0;}return -ENOIOCTLCMD; } #undef tiny_ioctl/* the real tiny_ioctl function. The above is done to get the small functions in the book */ static int tiny_ioctl(struct tty_struct *tty, unsigned int cmd,unsigned long arg) {switch (cmd) {case TIOCGSERIAL:return tiny_ioctl_tiocgserial(tty, cmd, arg);case TIOCMIWAIT:return tiny_ioctl_tiocmiwait(tty, cmd, arg);case TIOCGICOUNT:return tiny_ioctl_tiocgicount(tty, cmd, arg);}return -ENOIOCTLCMD; }static int tiny_proc_open(struct inode *inode, struct file *file) {return single_open(file, tiny_proc_show, NULL); }static const struct file_operations serial_proc_fops = {.owner = THIS_MODULE,.open = tiny_proc_open,.read = seq_read,.llseek = seq_lseek,.release = single_release, };static struct tty_operations serial_ops = {.open = tiny_open,.close = tiny_close,.write = tiny_write,.write_room = tiny_write_room,.set_termios = tiny_set_termios,.proc_fops = &serial_proc_fops,.tiocmget = tiny_tiocmget,.tiocmset = tiny_tiocmset,.ioctl = tiny_ioctl, };static struct tty_driver *tiny_tty_driver;static int __init tiny_init(void) {int retval;int i;/* allocate the tty driver */tiny_tty_driver = alloc_tty_driver(TINY_TTY_MINORS);if (!tiny_tty_driver)return -ENOMEM;/* initialize the tty driver */tiny_tty_driver->owner = THIS_MODULE;tiny_tty_driver->driver_name = "tiny_tty";tiny_tty_driver->name = "ttty";tiny_tty_driver->major = TINY_TTY_MAJOR,tiny_tty_driver->type = TTY_DRIVER_TYPE_SERIAL,tiny_tty_driver->subtype = SERIAL_TYPE_NORMAL,tiny_tty_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV,tiny_tty_driver->init_termios = tty_std_termios;tiny_tty_driver->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;tty_set_operations(tiny_tty_driver, &serial_ops);/* register the tty driver */retval = tty_register_driver(tiny_tty_driver);if (retval) {printk(KERN_ERR "failed to register tiny tty driver");put_tty_driver(tiny_tty_driver);return retval;}for (i = 0; i < TINY_TTY_MINORS; ++i)tty_register_device(tiny_tty_driver, i, NULL);printk(KERN_INFO DRIVER_DESC " " DRIVER_VERSION);return retval; }static void __exit tiny_exit(void) {struct tiny_serial *tiny;int i;for (i = 0; i < TINY_TTY_MINORS; ++i)tty_unregister_device(tiny_tty_driver, i);tty_unregister_driver(tiny_tty_driver);/* shut down all of the timers and free the memory */for (i = 0; i < TINY_TTY_MINORS; ++i) {tiny = tiny_table[i];if (tiny) {/* close the port */while (tiny->open_count)do_close(tiny);/* shut down our timer and free the memory */del_timer(tiny->timer);kfree(tiny->timer);kfree(tiny);tiny_table[i] = NULL;}} }module_init(tiny_init); module_exit(tiny_exit);
tiny_serial.c
/** Tiny Serial driver** Copyright (C) 2002-2004 Greg Kroah-Hartman (greg@kroah.com)** This program is free software; you can redistribute it and/or modify* it under the terms of the GNU General Public License as published by* the Free Software Foundation, version 2 of the License.** This driver shows how to create a minimal serial driver. It does not rely on* any backing hardware, but creates a timer that emulates data being received* from some kind of hardware.*/#include <linux/kernel.h> #include <linux/errno.h> #include <linux/init.h> #include <linux/slab.h> #include <linux/tty.h> #include <linux/tty_flip.h> #include <linux/serial.h> #include <linux/serial_core.h> #include <linux/module.h>#define DRIVER_AUTHOR "Greg Kroah-Hartman <greg@kroah.com>" #define DRIVER_DESC "Tiny serial driver"/* Module information */ MODULE_AUTHOR( DRIVER_AUTHOR ); MODULE_DESCRIPTION( DRIVER_DESC ); MODULE_LICENSE("GPL");#define DELAY_TIME HZ * 2 /* 2 seconds per character */ #define TINY_DATA_CHARACTER 't'#define TINY_SERIAL_MAJOR 240 /* experimental range */ #define TINY_SERIAL_MINORS 1 /* only have one minor */ #define UART_NR 1 /* only use one port */#define TINY_SERIAL_NAME "ttytiny"#define MY_NAME TINY_SERIAL_NAMEstatic struct timer_list *timer;static void tiny_stop_tx(struct uart_port *port) { }static void tiny_stop_rx(struct uart_port *port) { }static void tiny_enable_ms(struct uart_port *port) { }static void tiny_tx_chars(struct uart_port *port) {struct circ_buf *xmit = &port->state->xmit;int count;if (port->x_char) {pr_debug("wrote %2x", port->x_char);port->icount.tx++;port->x_char = 0;return;}if (uart_circ_empty(xmit) || uart_tx_stopped(port)) {tiny_stop_tx(port);return;}count = port->fifosize >> 1;do {pr_debug("wrote %2x", xmit->buf[xmit->tail]);xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);port->icount.tx++;if (uart_circ_empty(xmit))break;} while (--count > 0);if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)uart_write_wakeup(port);if (uart_circ_empty(xmit))tiny_stop_tx(port); }static void tiny_start_tx(struct uart_port *port) { }static void tiny_timer(unsigned long data) {struct uart_port *port;struct tty_struct *tty;port = (struct uart_port *)data;if (!port)return;if (!port->state)return;tty = port->state->port.tty;if (!tty)return;/* add one character to the tty port *//* this doesn't actually push the data through unless tty->low_latency is set */tty_insert_flip_char(tty, TINY_DATA_CHARACTER, 0);tty_flip_buffer_push(tty);/* resubmit the timer again */timer->expires = jiffies + DELAY_TIME;add_timer(timer);/* see if we have any data to transmit */tiny_tx_chars(port); }static unsigned int tiny_tx_empty(struct uart_port *port) {return 0; }static unsigned int tiny_get_mctrl(struct uart_port *port) {return 0; }static void tiny_set_mctrl(struct uart_port *port, unsigned int mctrl) { }static void tiny_break_ctl(struct uart_port *port, int break_state) { }static void tiny_set_termios(struct uart_port *port,struct ktermios *new, struct ktermios *old) {int baud, quot, cflag = new->c_cflag;/* get the byte size */switch (cflag & CSIZE) {case CS5:printk(KERN_DEBUG " - data bits = 5\n");break;case CS6:printk(KERN_DEBUG " - data bits = 6\n");break;case CS7:printk(KERN_DEBUG " - data bits = 7\n");break;default: // CS8printk(KERN_DEBUG " - data bits = 8\n");break;}/* determine the parity */if (cflag & PARENB)if (cflag & PARODD)pr_debug(" - parity = odd\n");elsepr_debug(" - parity = even\n");elsepr_debug(" - parity = none\n");/* figure out the stop bits requested */if (cflag & CSTOPB)pr_debug(" - stop bits = 2\n");elsepr_debug(" - stop bits = 1\n");/* figure out the flow control settings */if (cflag & CRTSCTS)pr_debug(" - RTS/CTS is enabled\n");elsepr_debug(" - RTS/CTS is disabled\n");/* Set baud rate */baud = uart_get_baud_rate(port, new, old, 0, port->uartclk/16);quot = uart_get_divisor(port, baud);//UART_PUT_DIV_LO(port, (quot & 0xff));//UART_PUT_DIV_HI(port, ((quot & 0xf00) >> 8)); }static int tiny_startup(struct uart_port *port) {/* this is the first time this port is opened *//* do any hardware initialization needed here *//* create our timer and submit it */if (!timer) {timer = kmalloc(sizeof(*timer), GFP_KERNEL);if (!timer)return -ENOMEM;}init_timer(timer);timer->data = (unsigned long)port;timer->expires = jiffies + DELAY_TIME;timer->function = tiny_timer;add_timer(timer);return 0; }static void tiny_shutdown(struct uart_port *port) {/* The port is being closed by the last user. *//* Do any hardware specific stuff here *//* shut down our timer */del_timer(timer); }static const char *tiny_type(struct uart_port *port) {return "tinytty"; }static void tiny_release_port(struct uart_port *port) {}static int tiny_request_port(struct uart_port *port) {return 0; }static void tiny_config_port(struct uart_port *port, int flags) { }static int tiny_verify_port(struct uart_port *port, struct serial_struct *ser) {return 0; }static struct uart_ops tiny_ops = {.tx_empty = tiny_tx_empty,.set_mctrl = tiny_set_mctrl,.get_mctrl = tiny_get_mctrl,.stop_tx = tiny_stop_tx,.start_tx = tiny_start_tx,.stop_rx = tiny_stop_rx,.enable_ms = tiny_enable_ms,.break_ctl = tiny_break_ctl,.startup = tiny_startup,.shutdown = tiny_shutdown,.set_termios = tiny_set_termios,.type = tiny_type,.release_port = tiny_release_port,.request_port = tiny_request_port,.config_port = tiny_config_port,.verify_port = tiny_verify_port, };static struct uart_port tiny_port = {.ops = &tiny_ops, };static struct uart_driver tiny_reg = {.owner = THIS_MODULE,.driver_name = TINY_SERIAL_NAME,.dev_name = TINY_SERIAL_NAME,.major = TINY_SERIAL_MAJOR,.minor = TINY_SERIAL_MINORS,.nr = UART_NR, };static int __init tiny_init(void) {int result;printk(KERN_INFO "Tiny serial driver loaded\n");result = uart_register_driver(&tiny_reg);if (result)return result;result = uart_add_one_port(&tiny_reg, &tiny_port);if (result)uart_unregister_driver(&tiny_reg);return result; }module_init(tiny_init);
转载于:https://www.cnblogs.com/pengdonglin137/p/4321936.html
tiny4412 串口驱动分析五 --- LDD3上TTY驱动程序源码相关推荐
- tiny4412 串口驱动分析九 --- shell终端
作者:彭东林 邮箱:pengdonglin137@163.com 开发板:tiny4412ADK+S700 4GB Flash 主机:Wind7 64位 虚拟机:Vmware+Ubuntu12_04 ...
- linux串口驱动分析
linux串口驱动分析 硬件资源及描写叙述 s3c2440A 通用异步接收器和发送器(UART)提供了三个独立的异步串行 I/O(SIO)port,每一个port都能够在中断模式或 DMA 模式下操作 ...
- wince串口驱动分析(转)
wince串口驱动分析 串行通讯接口主要是指UART(通用串行)和IRDA两种.通常的串行连接电气连接上有3wire和9wire两种.3wire的接线方式下定义了发送.接收和地三根连接.其用途就如名称 ...
- linux tty core code,linux tty core 源码分析(7)
套接字和终端通常都具有异步通知机制,即应用程序可以在数据可用的时候接收到一个信号SIGIO而不需要去轮询关注的数据.但是当对于多个数据源时,应用不能区分SIGIO的来源.为了实现异步通知机制,应用程序 ...
- Android上百实例源码分析以及开源分析集合打包
感谢网友banketree的收集,压缩包的内容如下: 1.360新版特性界面源代码 实现了360新版特性界面的效果,主要涉及到Qt的一些事件处理与自定义控件.但源码好像是c++. 2.aidl跨进程调 ...
- Linux内核学习(五):linux kernel源码结构以及makefile分析
Linux内核学习(五):linux kernel源码结构以及makefile分析 前面我们知道了linux内核镜像的生成.加载以及加载工具uboot. 这里我们来看看linux内核的源码的宏观东西, ...
- 小程序 多张图片上传(源码分享+实现分析)
本篇文章以小程序中的代表[微信小程序]为例,分享一下在微信小程序中实现多图上传的源码实现. PS:其它小程序 和 uni-app 也可通用该思路实现. 代码片段(可导入微信WEB开发者工具体验):ht ...
- Linux虚拟化KVM-Qemu分析(三)之KVM源码(1)kvm_init
Table of Contents 1. 概述 2. KVM初始化 2.1 kvm_arch_init 2.1.1 init_hyp_mode 2.1.2 init_subsystems 2.2 mi ...
- 深度分析 Java 的 ClassLoader 机制(源码级别)(转)
写在前面:Java中的所有类,必须被装载到jvm中才能运行,这个装载工作是由jvm中的类装载器完成的,类装载器所做的工作实质是把类文件从硬盘读取到内存中,JVM在加载类的时候,都是通过ClassLoa ...
- 深度分析Java的ClassLoader机制(源码级别)
转载自 深度分析Java的ClassLoader机制(源码级别) Java中的所有类,必须被装载到jvm中才能运行,这个装载工作是由jvm中的类装载器完成的,类装载器所做的工作实质是把类文件从硬盘读取 ...
最新文章
- 自定义分辨率软件_苹果剪辑软件Final Cut Pro X导出竖屏视频教程
- 3D打印机分类与速度
- [云炬创业管理笔记]第十章商业计划书答辩测试2
- VC2008的运行库问题。
- linux 进程与锁,linux 中的进程与锁
- python中的ix是啥_python pandas (ix iloc loc) 的区别
- JavaScript中如何自定义属性操作
- SpringBoot+Vue项目上手
- 给 Java 说句公道话
- 下载npm并配置npm环境
- VMware14秘钥
- 适合于图像处理方向的SCI期刊杂志列表
- ROG GL552VW BIOS 编程器官方固件
- 数据结构试卷及答案(七)
- Win:在 Windows Server 中的 NIC Teaming
- PS学习笔记(88天和我一起学会PS)(5/88)
- 怎么在HTML中加入热区,关于网页点击热区图
- python 正则表达式匹配
- Uniapp离线打包使用高德地图教程及常见问题
- USACO 1月 2021-2022 January Contest Silver银组 题解