日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > linux >内容正文

linux

linux 串口驱动

發(fā)布時間:2024/8/1 linux 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 linux 串口驱动 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

代碼走讀記錄

目錄

1.? 核心數(shù)據(jù)結(jié)構 ops

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

? ?2.1??cdns_uart_startup 即打開串口

2.2 start tx? 即發(fā)送使能

2.3 中斷發(fā)送與軟件隊列的同步

3. 中斷處理程序

3.1 RX 中斷處理



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

1.? 核心數(shù)據(jù)結(jié)構 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); //這里采用鎖,多個進程同時調(diào)用支持?為啥禁止中斷/* Disable the TX and RX */writel(CDNS_UART_CR_TX_DIS | CDNS_UART_CR_RX_DIS,port->membase + CDNS_UART_CR); //禁用發(fā)送和接收/* 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門限設置。門限的大小和波特率相關,可以控制中斷的數(shù)目/** Receive Timeout register is enabled but it* can be tuned with a module parameter*/writel(rx_timeout, port->membase + CDNS_UART_RXTOUT); // 設置接收超時,即某些字節(jié)在FIFO中,但軟件一直沒有讀取,超過此時間設定后,硬件產(chǎn)生中斷,通知軟件獲取,實際也和波特率相關。/* 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;}//使能接收中斷,開始接收數(shù)據(jù)/* 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);elsewritel(CDNS_UART_RX_IRQS, port->membase + CDNS_UART_IER);return 0; }

綜上,代碼open的主要操作為:

1)?禁用發(fā)送和接收

2) 使能接收

3)? 設置串口工作模式

4) 接收FIFO門限設置。門限的大小和波特率相關,可以控制中斷的數(shù)目

5)設置接收超時,即某些字節(jié)在FIFO中,但軟件一直沒有讀取,超過此時間設定后,硬件產(chǎn)生中斷,通知軟件獲取,實際也和波特率相關。

6)? 清除中斷

7)掛接中斷處理

8) 使能接收中斷,開始接收數(shù)據(jù)

以上代碼流程中 spin_lock_irqsave 禁止中斷與采取鎖的背景考慮是? 多線程 是lock,那么中斷,是怕在操作的過程中有串口中斷上來,而此時中斷處理程序還沒上來?

2.2 start tx? 即發(fā)送使能

? 將數(shù)據(jù)從軟件緩存隊列里面放到TX FIFO 中,并進行發(fā)送及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給的緩存里面沒有數(shù)據(jù),即實際沒有數(shù)據(jù)需要發(fā)送,因而直接返回。return;cdns_uart_handle_tx(port); //如果軟件有數(shù)據(jù)發(fā)送,則在此處填充硬件TX FIFO,此處填充,由于上面已經(jīng)將TX 發(fā)送使能打開了,所以邊往fifo里面寫,串口邊從FIFO讀取并發(fā)送出去。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 中斷發(fā)送與軟件隊列的同步

即 硬件將軟件緩存中的數(shù)據(jù)發(fā)送的差不多時,此時再次喚醒軟件往緩存中增加數(shù)據(jù).

static void cdns_uart_handle_tx(void *dev_id) {struct uart_port *port = (struct uart_port *)dev_id;unsigned int numbytes;//從軟件緩存里面取數(shù)據(jù),然后寫入到TX FIFO中。//以下這個代碼用于喚醒軟件進程繼續(xù)往緩存里面寫數(shù)據(jù),當緩存中的數(shù)據(jù)小于 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. 中斷處理程序

? ??分為接收和發(fā)送中斷。?

? ?

static irqreturn_t cdns_uart_isr(int irq, void *dev_id) {struct uart_port *port = (struct uart_port *)dev_id; //支持多個串口,獲取此中斷對應的串口實例,以便獲取資源信息,避免數(shù)據(jù)的混亂。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); //針對發(fā)送處理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;// 主要過程循環(huán)讀取RX FIFO中的數(shù)據(jù),并判斷數(shù)據(jù)的正確性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驅(qū)動學習 - UART驅(qū)動的write操作流程_sbctsp的博客-CSDN博客? (此篇文章,主要參考write_wait,我們在中斷處理發(fā)送流程中看到對此wakeup的操作)

總結(jié)

以上是生活随笔為你收集整理的linux 串口驱动的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 日韩av专区片| 一区二区三区在线免费视频 | 国内性爱视频 | 国产精品麻豆果冻传媒在线播放 | 国产一线二线在线观看 | 欧美精品www | 色婷五月天 | 久久亚洲一区 | 天堂中文在线资 | 波多野结衣一二三区 | 国产一区二区三区在线 | 国产成人8x视频一区二区 | 色伊人av| 国产成人在线看 | 小箩莉末发育娇小性色xxxx | 一个色综合网站 | 在线观看国产一区二区三区 | 人妻丰满熟妇av无码区 | 日本福利视频导航 | 亚洲免费精品视频在线观看 | 日韩一卡二卡三卡四卡 | 欧美日韩一区二区中文字幕 | 欧美日韩电影一区 | 性色av一区二区三区免费 | 精品无码一区二区三区爱欲 | 午夜在线一区二区三区 | 伊人在线视频 | 精品国产18久久久久久二百 | 色哟哟av | 国产人妻777人伦精品hd | 偷拍第一页| 免费av成人 | 色欲亚洲Av无码精品天堂 | 国产成人免费电影 | 日韩国产欧美一区二区三区 | 在线观看第一页 | 不卡精品视频 | www.17c.com喷水少妇 | 欧美午夜小视频 | 色久综合 | 国产黑丝视频 | 国产精品视频一 | 综合色在线观看 | 日韩av中文在线 | 精品国产不卡 | 素人一区 | 五月婷婷深深爱 | 国产三级三级三级 | 午夜激情导航 | 亚洲综合站 | 免费看a网站 | 国产日韩综合 | 国产精品第七页 | 欧美一级专区 | 动漫美女放屁 | 国产网站大全 | 免费毛片网站在线观看 | 韩国三级做爰视频 | 久久久香蕉 | 亚洲av无码乱码国产麻豆 | 亚洲色图40p | 日韩黄色成人 | 国产精品四虎 | 欧美亚洲另类图片 | 日日碰日日操 | 日本激情视频网站 | av中文一区| 老妇女玩小男生毛片 | 国产欧美一区二区三区在线看蜜臀 | 我要看18毛片 | 147人体做爰大胆图片成人 | 一级免费观看 | 99精品一区二区三区 | 亚洲无吗在线观看 | 日韩一级完整毛片 | 欧美色图激情小说 | 欧洲久久久久久 | www.日韩高清| 午夜天堂精品 | 欧美七区 | 精品偷拍一区 | 欧美99| av大全在线播放 | 欧美精品成人久久 | 亲子伦视频一区二区三区 | 香蕉一区二区 | 国产剧情一区二区三区 | jizz亚洲女人 | 日韩欧美综合 | 国产高清一| 久久综合日本 | 欧美日韩视频无码一区二区三 | 欧美成人免费播放 | 丁香六月激情综合 | 日本乱淫视频 | 国产欧美日韩三级 | 国产成人在线视频免费观看 | 亚洲色图影院 | 欧美人与zoxxxx另类 |