精华内容
下载资源
问答
  • linux安装串口驱动程序
    千次阅读
    2021-03-19 16:54:53

    准备工作

    1. 在控制台输入lsmod,先看看能否检测到这个设备,就看有没有pl2303字眼可以了。如果有,则不需要再装驱动。
    2. 另外如果有的话最好再用dmesg| grep usb查找如果看到:

    drivers/usb/serial/usb-serial.c: USB Serial support registered for Generic

    就说明设备已被识别,然后往下看

    drivers/usb/serial/usb-serial.c: USB Serial support registered for PL-2303
    usb 2-2: PL-2303 converter now attached tottyUSB0 (or usb/tts/0 for devfs)

    如果没有则需要驱动程序,一般硬件厂商都会提供,如果真的没有的话就只有到网上下载了,一般2.6内核以上的都支持。
    3. 安装完毕后再输入这个命令瞧瞧,是否安装成功。
    lsmod | grep usbserial

    如果有usbserial,说明系统支持USB转串口。

    4. 驱动安装完毕后,就需要安装串口软件,这里推荐 cutecom 和 putty
    cutecom 安装 sudo apt-get install cutecom
    putty 安装 sudo apt install puttysudo pacman -S putty
    5. 然后启动 cutecom 命令sudo cutecom, 之后你就可以看到哪些串口正在连接状态
    6. 当开发板启动后,我们需要传入 elf 或 bin 文件,此时需要用到 tftp ,在控制台输入 :
    sudo apt-get install xinetd
    sudo apt-get install tftp tftpd
    并等待安装完成后,输入:sudo vi /etc/xinetd.d/tftp

    输入 i ,进入插入模式,随后输入下面的代码

    service tftp
    {
            socket_type = dgram
            protocol = udp
            wait = yes
            user = root
            server = /usr/sbin/in.tftpd
            server_args = -s /xxx/xxx/xxx   ## tftp的文件目录 
            disable = no
            per_source = 11
            cps = 100 2
            flags = IPv4
    }
    

    随后按 esc 输入wq! 保存

    7. 第一次启动时和每次更换目录时都要执行 sudo /etc/init.d/xinetd restart,不然会找不到文件
    8. 喜欢用 putty 的可以 在控制台输入 sudo putty 运行程序
    更多相关内容
  • Linux串口驱动程序

    2018-06-04 10:37:04
    linux 设备下串口驱动程序,供和Linux设备连接的rs485/rs232等串口设备通信。源码性能稳定,速度快
  • 在双核移动终端中进行验证,两芯片通过串口进行芯片间通信,实验结果证明了设计的高速串口驱动具有较好的可靠性和可行性。
  • 嵌入式Linux串口驱动程序设计课程设计
  • 基于Linux的SC16IS752的串口驱动程序设计.pdf
  • 一、PCI转串口卡安装 型号NetMos Nm9835CV1、插入PCI卡到主机2、启动 Linux,打开终端3、输入命令:#setserial /dev/ttyS0 -a (COM-1)显示内容:/dev/ttyS0, Line 0, UART: 16550A, Port: 0x3f8, irq: 4Baud_base: ...

    一、PCI转串口卡安装  型号NetMos Nm9835CV

    1、插入PCI卡到主机

    2、启动 Linux,打开终端

    3、输入命令:#setserial  /dev/ttyS0 -a   (COM-1)

    显示内容:/dev/ttyS0, Line 0,  UART: 16550A, Port: 0x3f8, irq: 4

    Baud_base: 115200, clos_delay: 50, divisor: 0

    closing_wait: 3000, closing_wait2: infinite

    Flags: spd_normal skip_test

    4、输入命令:#setserial  /dev/ttyS2 -a   (COM-3)

    显示内容:/dev/ttyS2, Line 2,  UART: unknown, Port: 0x3e8, irq: 4

    Baud_base: 115200, clos_delay: 50, divisor: 0

    closing_wait: 3000, closing_wait2: infinite

    Flags: spd_normal skip_test

    第3、4步操作的目的主要是对主机自带串口及PCI扩展串口的区别。区别在于4显示的内容中UART:未unknow。不过若您检测这一步的时候 UART为16550A而不是unknow,证明你的系统已经认识了扩展的串口,不需要进一步设置,直接跳入第8步测试就可以了。

    5、需要输入命令查看一下您当前PCI检测的状态,以便对扩展串口进行设置

    #more  /proc/pci

    会显示出一堆的信息,不要因为看不懂而吓坏了。只要看到类似于这个PCI的信息,比如:PCI communication。。。或者Board with Nm9835CV part。。。   可能就是这个卡了,主要看看它的终端是多少,即irq多少及分配的地址是多少。例如:(不一定完全一样)

    Board with Nm9835CV part  irq:11

    I/O at 0xc000 [0xc001] serial port 1

    I/O at 0xc400 [0xc401] serial port 2

    I/O at 0xc800 [0xc801] not used

    I/O at 0xd000 [0xd001] not used

    I/O at 0xd400 [0xd401] not used

    I/O at 0xd800 [0xd801] not used

    6、知道PCI扩展卡的终端为11   串口1地址为0xc000  串口2地址为0xc400..

    就可以设置扩展的串口了。输入命令:

    setserial  /dev/ttyS2 port 0xc000 UART 16550A

    irq 11 Baud_base 115200

    另一个串口也类似的这么操作

    7、设置完毕后,就可以看看设置的情况了,输入第2步的命令看看,UART是否就是16500A 而不是 unknow了,如果是16500A恭喜,可能设置好咯,如果不是那就再检查一下吧。

    8、设置好了后是不是需要测试一下是否能够通讯呢?最好的办法是两台pc相连。如果pc为windows操作系统就用超级终端,是linux呢就用minicom吧

    9、装有linux的机器,首先需要设置一下监听的串口参数,输入命令

    #minicom -s

    进入界面后有个框弹出来,如果你还认识点英文单词的话,就回知道选择哪个的。应该是第三个吧,串口设置。

    将第一行更改为  /dev/ttyS2

    波特率也更改您所需要的。

    更改完后保存,保存的那个菜单应该是 save ... df1

    最后 exit

    10、在另外一台机器发送数据,这台机器minicom界面就能够收到信息了,成功后觉得挺有意思。另外不要把两个COM顺序弄翻了,如果弄错了哪个是COM3  COM4测试可就不灵便咯。

    二、USB-Serial (usb转串口) 用的是UTS4009P  usb to 4 port rs232 adapter(db9pin) cable(black)

    1、将设备u口插入pc

    2、输入#lsmod  先看看能否检测到这个设备,就看有没有pl2303字眼可以了。如果有,则不需要再装驱动。如果没有则需要驱动程序,那您就按照步骤安装吧,安装完毕后再输入这个命令瞧瞧,是否安装成功。

    3、检测步骤,检测步骤与第一的8条以后内容类似,只是需要主意的是设置串口设备的时候可能不是ttyS2了,有可能是ttyUSB0之类。最好能看看您/dev下面的文件。就因为开始我将这点忽略了,总是测试不通,着急了两天呢。最后终于搞定了。0b1331709591d260c1c78e86d0c51c18.png

    展开全文
  • linux 串口驱动

    千次阅读 2022-02-19 14:57:18
    记录 linux 内核中串口驱动相关流程及数据结构

    代码走读记录

    目录

    1.  核心数据结构 ops

    2. ops各个接口功能及在流程中的位置

       2.1  cdns_uart_startup 即打开串口

    2.2 start tx  即发送使能

    2.3 中断发送与软件队列的同步

    3. 中断处理程序

    3.1 RX 中断处理



    xilinx_uartps.c    drivers\tty\serial    49414    2021/10/26    885
     

    1.  核心数据结构 ops

    static const struct uart_ops cdns_uart_ops = {
    	.set_mctrl	= cdns_uart_set_mctrl,
    	.get_mctrl	= cdns_uart_get_mctrl,
    	.start_tx	= cdns_uart_start_tx,
    	.stop_tx	= cdns_uart_stop_tx,
    	.stop_rx	= cdns_uart_stop_rx,
    	.tx_empty	= cdns_uart_tx_empty,
    	.break_ctl	= cdns_uart_break_ctl,
    	.set_termios	= cdns_uart_set_termios,
    	.startup	= cdns_uart_startup,
    	.shutdown	= cdns_uart_shutdown,
    	.pm		= cdns_uart_pm,
    	.type		= cdns_uart_type,
    	.verify_port	= cdns_uart_verify_port,
    	.request_port	= cdns_uart_request_port,
    	.release_port	= cdns_uart_release_port,
    	.config_port	= cdns_uart_config_port,
    #ifdef CONFIG_CONSOLE_POLL
    	.poll_get_char	= cdns_uart_poll_get_char,
    	.poll_put_char	= cdns_uart_poll_put_char,
    #endif
    };

    2. ops各个接口功能及在流程中的位置

       2.1  cdns_uart_startup 即打开串口

        

    static int cdns_uart_startup(struct uart_port *port)
    {
    	struct cdns_uart *cdns_uart = port->private_data;
    	bool is_brk_support;
    	int ret;
    	unsigned long flags;
    	unsigned int status = 0;
    
    	is_brk_support = cdns_uart->quirks & CDNS_UART_RXBS_SUPPORT;
    
    	spin_lock_irqsave(&port->lock, flags); //这里采用锁,多个进程同时调用支持?为啥禁止中断
    
    	/* Disable the TX and RX */
    	writel(CDNS_UART_CR_TX_DIS | CDNS_UART_CR_RX_DIS,
    			port->membase + CDNS_UART_CR);   //禁用发送和接收
    
    	/* Set the Control Register with TX/RX Enable, TX/RX Reset,
    	 * no break chars.
    	 */
    	writel(CDNS_UART_CR_TXRST | CDNS_UART_CR_RXRST,
    			port->membase + CDNS_UART_CR);
    
    	while (readl(port->membase + CDNS_UART_CR) &
    		(CDNS_UART_CR_TXRST | CDNS_UART_CR_RXRST))
    		cpu_relax();
    
    	/*
    	 * Clear the RX disable bit and then set the RX enable bit to enable
    	 * the receiver.
    	 */
    	status = readl(port->membase + CDNS_UART_CR);
    	status &= ~CDNS_UART_CR_RX_DIS;
    	status |= CDNS_UART_CR_RX_EN;
    	writel(status, port->membase + CDNS_UART_CR);   //使能接收
    
    	/* Set the Mode Register with normal mode,8 data bits,1 stop bit,
    	 * no parity.
    	 */
    	writel(CDNS_UART_MR_CHMODE_NORM | CDNS_UART_MR_STOPMODE_1_BIT
    		| CDNS_UART_MR_PARITY_NONE | CDNS_UART_MR_CHARLEN_8_BIT,
    		port->membase + CDNS_UART_MR);
    
    	/*
    	 * Set the RX FIFO Trigger level to use most of the FIFO, but it
    	 * can be tuned with a module parameter
    	 */
    	writel(rx_trigger_level, port->membase + CDNS_UART_RXWM); //接收FIFO门限设置。门限的大小和波特率相关,可以控制中断的数目
    
    	/*
    	 * Receive Timeout register is enabled but it
    	 * can be tuned with a module parameter
    	 */
    	writel(rx_timeout, port->membase + CDNS_UART_RXTOUT); // 设置接收超时,即某些字节在FIFO中,但软件一直没有读取,超过此时间设定后,硬件产生中断,通知软件获取,实际也和波特率相关。
    
    	/* Clear out any pending interrupts before enabling them */
    	writel(readl(port->membase + CDNS_UART_ISR),
    			port->membase + CDNS_UART_ISR);     //  清除中断
    
    	spin_unlock_irqrestore(&port->lock, flags);   //释放锁
    
    	ret = request_irq(port->irq, cdns_uart_isr, 0, CDNS_UART_NAME, port);
    	if (ret) {
    		dev_err(port->dev, "request_irq '%d' failed with %d\n",
    			port->irq, ret);
    		return ret;
    	}
         //使能接收中断,开始接收数据
    	/* Set the Interrupt Registers with desired interrupts */
    	if (is_brk_support)
    		writel(CDNS_UART_RX_IRQS | CDNS_UART_IXR_BRK,
    					port->membase + CDNS_UART_IER);
    	else
    		writel(CDNS_UART_RX_IRQS, port->membase + CDNS_UART_IER);
    
    	return 0;
    }
    

    综上,代码open的主要操作为:

    1) 禁用发送和接收

    2) 使能接收

    3)  设置串口工作模式

    4) 接收FIFO门限设置。门限的大小和波特率相关,可以控制中断的数目

    5)设置接收超时,即某些字节在FIFO中,但软件一直没有读取,超过此时间设定后,硬件产生中断,通知软件获取,实际也和波特率相关。

    6)  清除中断

    7)挂接中断处理

    8) 使能接收中断,开始接收数据

    以上代码流程中 spin_lock_irqsave 禁止中断与采取锁的背景考虑是? 多线程 是lock,那么中断,是怕在操作的过程中有串口中断上来,而此时中断处理程序还没上来?

    2.2 start tx  即发送使能

      将数据从软件缓存队列里面放到TX FIFO 中,并进行发送及tx fifo 空中断的使能控制

    static void cdns_uart_start_tx(struct uart_port *port)
    {
    	unsigned int status;
    
    	if (uart_tx_stopped(port))
    		return;
    
    	/*
    	 * Set the TX enable bit and clear the TX disable bit to enable the
    	 * transmitter.
    	 */
    	status = readl(port->membase + CDNS_UART_CR);
    	status &= ~CDNS_UART_CR_TX_DIS;
    	status |= CDNS_UART_CR_TX_EN;
    	writel(status, port->membase + CDNS_UART_CR);
    
    	if (uart_circ_empty(&port->state->xmit))  //如果上层tty给的缓存里面没有数据,即实际没有数据需要发送,因而直接返回。
    		return;
    
    	cdns_uart_handle_tx(port); //如果软件有数据发送,则在此处填充硬件TX FIFO,此处填充,由于上面已经将TX 发送使能打开了,所以边往fifo里面写,串口边从FIFO读取并发送出去。
    
    	writel(CDNS_UART_IXR_TXEMPTY, port->membase + CDNS_UART_ISR);
    	/* Enable the TX Empty interrupt */
    	writel(CDNS_UART_IXR_TXEMPTY, port->membase + CDNS_UART_IER); //使能tx fifo空中断,这样
    }

    2.3 中断发送与软件队列的同步

    即 硬件将软件缓存中的数据发送的差不多时,此时再次唤醒软件往缓存中增加数据.

    static void cdns_uart_handle_tx(void *dev_id)
    {
    	struct uart_port *port = (struct uart_port *)dev_id;
    	unsigned int numbytes;
    
    	//从软件缓存里面取数据,然后写入到TX FIFO中。
        
        //以下这个代码用于唤醒软件进程继续往缓存里面写数据,当缓存中的数据小于 WAKUP_CHARS(此处是256)
    
    		if (uart_circ_chars_pending(
    				&port->state->xmit) < WAKEUP_CHARS)
    			uart_write_wakeup(port);
    	}
    }

        为什么不是软件一直往缓存里面写,而硬件一直从缓存里面读,而采取这种门限唤醒的机制呢?

    serdev-ttyport.c    drivers\tty\serdev    7921    2021/10/26    189
     

    // wake up a tty device 
    void tty_port_tty_wakeup(struct tty_port *port)
    {
    	port->client_ops->write_wakeup(port);
    }
    
    static const struct tty_port_client_operations client_ops = {
    	.receive_buf = ttyport_receive_buf,
    	.write_wakeup = ttyport_write_wakeup, //
    };
    
    //等待write_wait 的接口
    static void ttyport_wait_until_sent(struct serdev_controller *ctrl, long timeout)
    {
    	struct serport *serport = serdev_controller_get_drvdata(ctrl);
    	struct tty_struct *tty = serport->tty;
    
    	tty_wait_until_sent(tty, timeout);  //此处等待
    }

    3. 中断处理程序

        分为接收和发送中断。 

       

    static irqreturn_t cdns_uart_isr(int irq, void *dev_id)
    {
    	struct uart_port *port = (struct uart_port *)dev_id; //支持多个串口,获取此中断对应的串口实例,以便获取资源信息,避免数据的混乱。
    	unsigned int isrstatus;
    
    	spin_lock(&port->lock);  //端口锁,无中断禁止操作
    
    	/* Read the interrupt status register to determine which
    	 * interrupt(s) is/are active and clear them.
    	 */
    	isrstatus = readl(port->membase + CDNS_UART_ISR);
    	writel(isrstatus, port->membase + CDNS_UART_ISR);
    
    	if (isrstatus & CDNS_UART_IXR_TXEMPTY) {
    		cdns_uart_handle_tx(dev_id);    //针对发送处理
    		isrstatus &= ~CDNS_UART_IXR_TXEMPTY;
    	}
    
    	/*
    	 * Skip RX processing if RX is disabled as RXEMPTY will never be set
    	 * as read bytes will not be removed from the FIFO.
    	 */
    	if (isrstatus & CDNS_UART_IXR_RXMASK &&
    	    !(readl(port->membase + CDNS_UART_CR) & CDNS_UART_CR_RX_DIS))
    		cdns_uart_handle_rx(dev_id, isrstatus);  //针对接收处理
    
    	spin_unlock(&port->lock);
    	return IRQ_HANDLED;
    }

    3.1 RX 中断处理

    static void cdns_uart_handle_rx(void *dev_id, unsigned int isrstatus)
    {
    	struct uart_port *port = (struct uart_port *)dev_id;
    	struct cdns_uart *cdns_uart = port->private_data;
    	
    	char status = TTY_NORMAL;
    	bool is_rxbs_support;
    
    	is_rxbs_support = cdns_uart->quirks & CDNS_UART_RXBS_SUPPORT;
        // 主要过程循环读取RX FIFO中的数据,并判断数据的正确性
    	while ((readl(port->membase + CDNS_UART_SR) &
    		CDNS_UART_SR_RXEMPTY) != CDNS_UART_SR_RXEMPTY) {
    		
    		data = readl(port->membase + CDNS_UART_FIFO);
    		port->icount.rx++;
    		
    		tty_insert_flip_char(&port->state->port, data, status); //写入到缓存
    		isrstatus = 0;
    	}
    
    	tty_flip_buffer_push(&port->state->port); // 写入到缓存。这个接口比较重要
    }
    

    The Serial Device Bus (linuxfoundation.org)

    Serial TTY overview - stm32mpu (stmicroelectronics.cn)

    (3条消息) Linux tty驱动学习 - UART驱动的write操作流程_sbctsp的博客-CSDN博客  (此篇文章,主要参考write_wait,我们在中断处理发送流程中看到对此wakeup的操作)

    展开全文
  • 一、UART 驱动程序概述在嵌入式 Linux 系统中,串口被看成终端设备,终端设备(tty)的驱动程序分为三个部分:tty_coretty_disiciplinetty_driver包括3个结构体:uart_driveruart_portuart_ops( include/serial_core.h...

    一、UART 驱动程序概述

    在嵌入式 Linux 系统中,串口被看成终端设备,终端设备(tty)的驱动程序分为三个部分:

    tty_core

    tty_disicipline

    tty_driver

    包括3个结构体:

    uart_driver

    uart_port

    uart_ops( include/serial_core.h)

    因此实现一个平台的 UART 驱动程序只需要实现这3个结构体即可。

    二、uart_drvier 与 tty_driver 之间的关系

    25691ede19e75b3d934dab33e8a86cda.png

    uart_driver 结构体:

    uart_driver 结构体包含了串口设备名、串口驱动名、主次设备号、串口控制台(可选)等信息,还封装了 tty_driver(底层串口驱动,无需关心 tty_driver)。

    struct uart_driver

    {

    struct module *owner; //拥有该uart_driver的模块,一般为THIS_MODULE

    const char *driver_name; //串口驱动名,串口设备文件名以驱动名为基础

    const char *dev_name; //串口设备名

    int major; //主设备号

    int minor; //次设备号

    int nr; //该 uart_driver 支持的最大串口个数

    struct console *cons; //其对应的console。若该uart_driver支持serial console,否则为NULL

    ...........................

    struct uart_state *state;

    struct tty_driver *tty_driver; //uart_driver 封装了 tty_driver,使底层uart驱动不用关心tty_driver。

    };

    一个 tty 驱动程序必须注册/注销 tty_driver;

    一个 uart 驱动则变为注册/注销 uart_driver;

    使用如下接口:

    int uart_register_driver(struct uart_driver *drv);

    void uart_unregister_driver(struct uart_drvier *drv);

    int tty_register_driver(struct tty_driver *drv);

    void tty_unregister_driver(struct tty_driver *drv);

    实际上,uart_register_driver() 和 uart_unregister_drvier() 中分别包含了 tty_register_driver() 和 tty_unregister () 的操作,详情如下:

    uart_port结构体:

    uart_port 用于描述一个 UART 端口(直接对应于一个串口)的 I/O 端口或 I/O内存地址、FIFO大小、端口类型等信息。

    struct uart_port

    {

    spinlock_t lock; //串口端口锁

    unsigned int iobase; //IO 端口基地址

    unsigned char __iomem *membase; //IO 内存基地址,经映射(如ioremap)后的IO内存虚拟基地址

    unsigned int irq; //中断号

    unsigend int uartlock; //串口时钟

    unsigend int fifosize; //串口FIFO缓冲大小

    unsigned char x_char; //xon/xoff 字符

    unsigned char regshift; //寄存器位移

    unsigned char iotype; //IO访问方式

    unsigned char unused1;

    #define UPIO_PORT (0) //IO端口

    #deifne UPIO_HUB6 (1)

    #define UPIO_MEM (2) //IO内存

    #define UPIO_MEM32(3)

    #define UPIO_AU (4) //Aulx00 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 int read_status_mask; //关心的Rx error status

    unsigned int ignore_status_mask; //忽略的Rx error status

    struct uart_info *info; //重要,见下面

    struct uart_icount icount; //计数器 uart_icount 为串口信息计数器,包含了发送字符计数、接收字符计数等。在串口的发送中断处理函数和接收处理函数中,我们需要管理这些计数。

    struct console *cons; //console 结构体

    #ifdef CONFIG_SERIAL_CORE_CONSOLE

    unsigned long sysrq; //sysrq timeout

    #endif

    upf_t flags;

    #define UPF_FOURPORT ((__forceupf_t)(1 << 1))

    #define UPF_SAK ((__forceupf_t)(1 << 2))

    #define UPF_SPD_MASK ((__forceupf_t)(0x1030))

    #define UPF_SPD_HI ((__forceupf_t)(0x0010))

    #define UPF_SPD_VHI ((__forceupf_t)(0x0020))

    #define UPF_SPD_CUST ((__forceupf_t)(0x0030))

    #define UPF_SPD_SHI ((__forceupf_t)(0x1000))

    #define UPF_SPD_WARP ((__forceupf_t)(0x1010))

    #define UPF_SKIP_TEST ((__forceupf_t)(1 << 6))

    #define UPF_AUTO_IRQ ((__forceupf_t)(1 << 7))

    #define UPF_HARDPPS_CD ((__forceupf_t)(1 << 11))

    #define UPF_LOW_LATENCY ((__forceupf_t)(1 << 13))

    #define UPF_BUGGY_UART ((__forceupf_t)(1 << 14))

    #define UPF_MAGIC_MULTIPLIER((__force upf_t)(1 << 16))

    #define UPF_CONS_FLOW ((__forceupf_t)(1 << 23))

    #define UPF_SHARE_IRQ ((__forceupf_t)(1 << 24))

    #define UPF_BOOT_AUTOCONF ((__forceupf_t)(1 << 28))

    #define UPF_FIXED_PORT ((__forceupf_t)(1 << 29))

    #define UPF_DEAD ((__forceupf_t)(1 << 30))

    #define UPF_IOREMAP ((__forceupf_t)(1 << 31))

    #define UPF_CHANGE_MASK((__forceupf_t)(0x17fff))

    #define UPF_USR_MASK ((__forceupf_t)(UPF_SPD_MASK | UPF_LOW_LATENCY))

    unsigned int mctrl; //当前的 moden 设置

    unsigned int timeout; //character-based timeout

    unsigned int type; //端口类型

    const struct uart_ops *ops; //串口端口操作函数集

    unsigned int custom_divisor;

    unsigned int line; //端口索引

    resource_size_t mapbase; //IO内存物理基地址,可用于ioremap

    struct device *dev; //父设备

    unsigned char hub6; //this should be in the 8250 driver

    unsigned char suspended;

    unsigend char unused[2];

    void *private_data; //端口私有数据,一般为platform数据指针

    };

    串口核心层提供如下函数来添加一个端口:

    int uart_add_one_port(struct uart_driver *drv, struct uart_port *port);

    对上述函数的调用应该发生在 uart_register_driver() 之后, uart_add_one_port() 的一个最重要的作用是封装了 tty_register_device()。

    uart_add_one_port() 的“反函数”是 uart_remove_one_port(),其中会调用 tty_unregister_device(), 原型为:

    int uart_remove_one_port(struct driver *drv, struct uart_port *port);

    uart_info结构体:

    uart_info 有两个成员在底层串口驱动会用到: xmit 和 tty。用户空间程序通过串口发送数据时,上层驱动将用户数据保存在xmit;而串口发送中断处理函数就是通过xmit获取到用户数据并将它们发送出去。串口接收中断处理函数需要通过tty将接收到的数据传递给行规则层。

    在使用串口核心层这个通用串口tty驱动层的接口后,一个串口驱动要完成的主要工作将包括:

    定义uart_drvier、uart_ops、uart_port等结构体的实例,并在适当的地方根据具体硬件和驱动的情况初始化它们。(当然具体设备xxx的驱动可以将这些结构套在新定义的 xxx_uart_driver、xxx_uart_ops、xxx_uart_port之内)。

    在模块初始化时调用uart_register_driver() 和 uart_add_one_port()以注册UART驱动并添加端口,在模块卸载时调用uart_unregister_driver 和 uart_remove_one_port() 以注销UART驱动并移除端口。

    根据具体硬件的datasheet实现uart_ops中的成员函数,这些函数的实现成为UART驱动的主体工作。

    串口驱动之tty

    概念介绍:

    在Linux中,终端是一类字符设备,他包括多种类型,通常使用tty来简称各种中断设备串口终端(/dev/ttyS*):串口终端是使用串口连接的终端设备,Linux中将每一个串口设备都看作一个字符设备,这些串行端口对应的设备名称是/dev/ttySAC0 和 /dev/ttySAC1。

    控制台终端(/dev/console):

    在Linux中,计算中的输出设备通常被称为控制台终端(console)。这里特指printk()信息输出的。注意:/dev/console 是一个虚拟的设备,它需要映射到真正的tty上。比如通过内核启动参数“console=ttySAC0”就是把console映射到串口0,经常被内核所使用。

    注意:这里的终端是一个虚拟设备,虚拟设备必须和实际的设备联系起来,console=ttySAC0系统启动的时候就关联起来了。

    虚拟终端(/dev/tty*):

    当用户登录的使用使用的是虚拟终端,使用快捷键组合:ctrl+alt+[F1-F6]组合键就可以切换到tty1,tty2,tty3等上面去。tty1-tty6等成为虚拟终端,而tty0是当前使用的终端的一个别名。主要是提供给应用程序使用。

    tty架构

    da37488f516ffce80bf31a166ae70ad5.png

    tty核心:

    tty核心是对整个tty设备的抽象,并提供单一的接口。

    tty线路规划:

    tty线路规程是对数据的传输的格式化,比如需要实现某种协议,就需要将协议的实现代码放在该位置。

    tty驱动:

    是面向tty设备的硬件驱动

    注意:Linux中的获取回溯信息使用函数dump_stack()用来显示各种函数的调用信息。

    串口驱动程序的结构

    分析:串口驱动程序需要提供给用户读数据的功能,写数据,打开串口和关闭串口的功能。打开之前需要对肯定需要对串口进行初始化的工作。

    重要数据结构:

    struct uart_driver :一个串口对应一个串口驱动,用于描述串口结构

    struct uart_port:    有几个串口就对应几个port

    struct uart_ops:  UART相关操作函数结构体,对应相关串口所支持的操作函数集

    struct uart_state:UART状态结构

    struct uart_info: UART信息结构

    串口初始化:

    定义并描述串口:struct uart_driver;

    注册串口驱动程序:uart_register_driver;

    取出相应的串口,并初始化该取出的串口。

    串口驱动之打开驱动:

    系统调用过程:用户使用open()函数打开设备文件

    注意:

    打开设备文件肯定有对应的设备驱动文件打开函数:file_operations;

    在使用uart_register_driver()注册串口驱动的时候,该函数里面会调用函数tty_register_driver(),该函数会调用 cdev_init()函数和cdev_add()。

    从这里可以看出tty设备是属于字符设备。

    展开全文
  • PL2303 USB转RS232串口linux驱动程序,PL2303 linux驱动 亲测可用,可以做为你的学习设计参考。
  • linux串口驱动

    2019-01-25 10:28:41
    解决单片机驱动问题,里面含有各种版本的驱动,可以解决代码10的问题
  • Linux驱动之串口驱动配置

    千次阅读 2022-02-27 19:28:55
    串口驱动配置 1、 UART3 IO 节点创建 UART3 用到了 UART3_TXD 和 UART3_RXD 这两个 IO,因此要先在 iomuxc 中创建 UART3对应的 pinctrl 子节点,在 iomuxc 中添加如下内容: pinctrl_uart3: uart3grp { fsl,pins = ...
  • 学习Linux内核串口驱动的好资料
  • int parity = 'n; int flow = 'n; port = uart_get_console(s3c2410_ports, UART_NR, co; if (options uart_parse_options(options, &baud, &parity, &bits, &flow; return uart_set_options(port, co, baud, parit
  • 这是一个最简单的Linux下的C语言串口驱动程序,使用了最简单的方式实现了异步发送接收api接口,并且有demo使用例程。
  • CP2102是一款USB转UART桥接芯片,本站提供的CP2102驱动程序Linux版本,支持2.6.38 kernel (Ubuntu 11.04),属于官方正版好用,内有详细使用说明。
  • Linux串口驱动分析及移植

    千次阅读 2021-06-16 14:01:41
    1 概述     在Linux中,常碰到“控制台”、“终端”、“console”、“tty”等术语,也会经常使用一些设备文件:/dev/console...    UART与USART都是单片机上的串口通信, UART(universal asynchronous receiv
  • s3c410 arm uart串口驱动程序
  • uart.rar_linux串口驱动

    2022-09-22 23:52:52
    linux操作环境下,串口驱动程序编程实例。
  • 基于嵌入式Linux PXA270的蓝牙串口驱动程序设计.pdf
  • Linux系统TTY串口驱动实例详解

    千次阅读 2022-03-18 16:15:48
    简介 在Linux系统中,终端是一类字符型设备,它包括多种类型,通常使用tty来简称各种类型的...简单来分的话可以说成两层,一层是下层我们的串口驱动层,它直接与硬件相接触,我们需要填充一个 struct uart_ops 的结构体
  • 安装linux系统的电脑,加上串口卡1托4 或 1托8后,都需要使用这个驱动程序进行驱动安装安装命令看readme文件。尤其是新版本linux系统,内核5的都需要最新的驱动程序,否则无法成功安装驱动,购买串口卡自带驱动...
  • * 第7章 串口驱动程序 * 7.1 串口概述 1异步串行通信 所谓异步传输是指异步通信的数据传输过程中接收时钟与发送时钟是不同步的即发送端和接收端都有自己独立的时钟和相同的速度约定而在串行总线上则没有时钟信号的...
  • UART 16550 串口驱动程序linux源代码
  • 2410自带有三个串口,但mizi linux中自带的驱动均为RS232的,因为485是半双工的,比232多了一个方向控制信号,所以linux的自带驱动并不适合485,需要进行一定的修改,步骤如下。1. 首先硬件方面肯定要改动,假设我们...
  • Linux串口驱动程序设计例子 Linux串口驱动程序设计例子
  • Ubuntu的下USB转串口芯片驱动程序安装CP210X,pl2303安装,适用于Linux,解决在Linux下找不到USB串口的问题
  • Linux CH340驱动安装

    千次阅读 2022-01-12 13:30:18
    1、下载驱动安装包 地址CH340/CH341的USB转串口LINUX驱动程序,支持32/64位系统 2、根据自己的内核版本将下载的驱动更改为相对应的内容(ch34x.c),我的内核版本为 5.4.10- rt5,选择如下版本 官方给出的不同内核...
  • linux串口驱动该怎么写是的,串口设备也是字符设备呀 但是一般serial 0会被当作console。linux下串口驱动如何实现?用驱动程序啊 不过现在一般都能自动安装如何查看linux下串口是否可用?串口名称等?查看串口是否...
  • Linux 零调制解调器仿真器 (tty0tty) 是 Linux 的内核模块虚拟串行端口驱动程序。 这将创建虚拟 tty 端口对并使用任何一对将一个基于 tty 串行端口的应用程序连接到另一个。 有一个使用伪终端的版本(UNIX 98 风格)...
  • 文章目录0 参考链接1 查看电脑的内核版本2 下载安装包3 编译安装0 参考链接https://blog.csdn.net/hnlyzxy123/article/details/82181027https://blog.csdn.net/jazzsoldier/article/details/70169732下载链接...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 30,892
精华内容 12,356
热门标签
关键字:

linux安装串口驱动程序