串口 終端(原創)

----------- 使 串口在進入idle後繼續輸出log ------------ java

默認是不能的, 只要下面的, 就能不斷的輸出串口log: linux

adb shell
setprop persist.uartconsole.enable 1android

 

  串口線標準不同, 有一根串口線能打出 feature phone的串口數據。 但6795的數據就打不出來。 有1.8伏的,和2.8伏的。要肯定串口線用的對不對。 裏面是轉換芯片的。 c++

  --------------------------- 串口芯片, 配置, 使用 --------------- 
  串口芯片集成到了主芯片內部, 串口芯片通常包括, 接收緩衝區, 發送緩衝區. 這是硬件緩衝區.  主芯片通常有三條串口線, 就像能夠有多條i2c總線.
 
  相應的gpio能夠選擇配置成串口, 並非每一個gpio都能配置成串口, 從gpio配置表dws文件, 能夠看到gpio是否支持串口模式. 
    
  從feature phone調試來看, 串口只能被一個模塊使用, 能夠用setowner函數來切換被哪一個模塊使用. 有一個nv項會決定, 串口給哪一個模塊用. 

  每次串口在接收到數據時, 都會發送串口消息, 在feature phone中, 消息中都會指定發給哪一個task. task中都會有一個循環, 來接收task.  循環中會相應的receive函數, 接收消息, 若是沒消息過來, 則會阻塞. 
 
  實際中遇到的問題:
 
  1.  在打開串口時, 原本要打開串口1, 而打開了串口3, 結果Task循環中, 一直沒收到消息.
 
  2. 配置串口時, 沒調setowner, 致使open串口時指定的模塊, 與串口的owner不一致, 致使電流一直在巨大跳變. 一插上usb, 電腦的services進程佔用40%
 
  3. uart_getbytes函數的指定的軟件緩衝區length大小爲0, 致使硬件緩衝區的數據沒有被接收, 串口驅動的接收標誌沒有被置位,
     致使下一次串口接收數據時, 沒有發串口消息. 把length改大便可.  
    
  4. 串口的owner切換, 默認配置的是給at模塊用. 爲了給2502傳送數據, 添加一個at命令, 完成模塊切換. 即將串口由at模塊轉給自定義的task模塊.
 
  5.  task 配置,  在hal_task_config.h配置,  編譯不過. 要在app_task_config.h配置, task所作的事情, 應該都屬於mmi層. 對應linux, 應該是串口用戶空間編程.
 
  6. 因持續收到的串口消息沒有釋放, 致使收到第600個左右的字節時, 系統掛掉.
  先說一下消息的通常機制:
  java, c, c++, 消息架構都是, 消息對象裏都會指定消息的接收者, 消息的接收者, 通常都是一個循環,
  循環裏有個函數會等待消息, 若是消息沒來, 就會阻塞在那, 若是消息過來, 纔會繼續執行.
  mtk Task接收uart消息, 就是使用這個機制.
  串口有數據發來, 就會有個串口消息發出來, 經過對串口設置owner, 即該task的mod id, 這樣對消息體裏id就指定這個task. 消息發送這個task.
 
  task while 循環接收到消息, 實際接收的消息的對象, 通常的機制都是由接收者來釋放這個消息在內存中申請的空間.
 
  若沒有釋放, 這裏碰到一個問題, 因爲空間不斷泄漏, 到收到第600多個字節, 消息對象數量不斷增多, 泄漏的內存不斷增大, 致使系統掛住.
 
  串口工具備時at命令無響應, 串口工具從新打開就好shell

 

------------------ cts rts配置 -----------------
  解釋cts/rts流控,要從接收緩衝區提及. 當初遇到了什麼問題, 而想出了這個東西. 編程

  流控是爲了接收緩衝區沒有準備好, 發送方還在發數據的問題, 數據丟失的問題. 架構

  解決的辦法, 就是多連一條線, 接收方經過控制這根線的高低電平, 來告訴發送方, 接收緩衝區是否準備好. app

   接收緩衝區若是沒準備好, 會把這根線拉高,  若是準備好, 就把這根線拉低.
  從術語上講, 這根線在rx這邊, 對應引腳是rts,  在tx那邊, 接引腳cts.  在數據沒準備好時,   rts拉低. 默認rts配置成內部拉高. 異步

 

接線:函數

rx要接到對方的tx, tx要接到對方的rx. 在調ble與2502通信時, ble要配成與2502相反. 

rts要接到對方的cts.  rts電位由接收方控制.

 

經過控制電平, 通知對方:

當接收方還沒準備好, 接收方會把rts拉高, 即發送方的cts被拉高, 這樣發送方就知道接收發沒有準備好, 就不發送了.
當接收方準備好時, 接收方會把rts拉低, 即發送方的cts被拉低, 這樣發送方就知道接收發準備好, 就發送數據.

 

gpio配置:

從Datashee可確認, 打開dws, 可看到支持硬件流控的gpio. 2502只有兩個gpio支持硬件流控,  從gpio選項中可確認.

 

測試硬件是否起做用:

 

 

對於ble與2502, 由於2502給ble發送大數據, ble是接收方, 因此rts信號由接收方控制, 這就是ble支持硬件流控.  而2502的cts收到這個信號, 能不發送數據, 說明2502也支持硬件流控.

 

分包大小要受對方緩衝區限制, 最大不能超過對方接收緩衝區. 

 

--------------------  反接, 看另外一方數據  --------------------

uart , 串口線的白線接到板子上的Tx, 即接到板子的發she點, 即看板子的串口輸出信息.

 

ble到2502的串口總線, 引出的tx, rx測試點, 是以2502來命名的,

若是想接收2502的串口發出信息, 就接點tx點.
若是想看ble的串口發出發出信息, 就接到rx點.
調試時常常要看ble的發出信息. 因此uart反接一下.
一語擊中要點, 又不賣nong.
能夠從插頭, 直接引出針來.

修行須要積點滴以成大海的yi力

 

 

-----  串口速率 ---------

   
   串口傳輸速率, 50K, 20K分別對應哪一個檔. 115200 對應多少.  除以8, 得14402, 即15K. 是吧
   串口傳輸速率有兩種表示方法, 一種bps, 如115200. 一種是KBps, 通常一個數據佔8位.  因此115200對應的是14.4KBps. 理論上每秒傳14K.   傳輸速率是否受接收方的限制. 

 

---------- 協調串口數據傳輸的信號線 ----------------

uart能夠有18根信號線, unix環境只用了6根.


GND - Logic Ground 地線, 提供了一個參考電壓, 基於這個參考電壓, 有兩種電壓, space電壓, mark電壓.
TXD - Transmitted Data發送信號線
RXD - Received Data接收信號線
DCD - Data Carrier Detect表示另外一端已經鏈接好的信號線, space電壓表示另外一端已經鏈接, mark電壓表示沒準備好
DTR - Data Terminal Ready表示另外一端是否已經準備好的信號線, space電壓表示已經準備好
CTS - Clear To Send space電壓表示本地這端能夠送出更多數據
RTS - Request To Send space電壓表示本地已經準備好了數據能夠傳送.

之後再看到這些字母就不犯迷糊了. 這些信號線都是來協調數據傳送的, 就是爲了給你百分之百的保證. 纔有了這麼多信號線.

芯片從串行總線接到數據, 數據都是一個字節一個字節傳送的, 必須知道字節的開始位置, 與結束位置.
串行線在沒有數據傳送時, 都是mark電壓.
在變到space電壓, 說明有數據來了,
每一個字節前都有一個space電壓的start位, 表示字節的開始
在每一個字節的最後都一個parity校驗位, 和一箇中止位.

數據通常表示爲8N1, 表示8個數據位, 無校驗位, 有一箇中止位.
7E1 表示7個數據位, Even偶數校驗位, 和一箇中止位.


-------------
雙工之雙字,就表示雙向, 接收與發送兩個方向
全雙工,  就是同一時刻, 能夠同時接收與發送數據,  一個發送線, 一個接收線
半雙工, 在同一時刻, 只能發送, 或只能接收.

----------------
爲了協調串行數據流, 有軟件和硬件兩種方法,
軟件方式便是用特殊字符來開始或結束數據流, 這些特殊字符有: 開始的有XON, DC1, 結束的有XOFF, DC3.
硬件方式, 接收方準備好時, 將CTS置爲space電壓, 沒有準備好就置爲mark電壓.  這樣發送方就知道能夠發送數據了.  CLEAR to send, 即告訴發送方能夠發送了.
發送方準備好時,  將RTS置爲space電壓, 這樣接收方就知道能夠接收數據了.   Request to send, 即發送請求發送數據, 讓接收方接收.
這就是CTS/RTS通知機制.  

有數據正在傳輸時, 接收信號線和發送信號線, 都會保持在mark電壓. 若是傳着傳着, 從mark電壓掉到space電壓,  而且持續了1/4秒, 說明傳輸break了, 這時break條件就存在了.
break通常被用來重置數據線.

 

---------------  串口線 -------------
串口線的地線是必須鏈接的, 若只看log, 則只連tx和地線, tx對應白線. 若要經過串口發at命令, 則要tx, rx, 地線三根線.

電源引出的線有可能燒掉, 用萬用表量一下電阻, 正常的會有一個值.

2502引出的uart1, 與藍牙通訊, 接收藍牙發來的At命令, (應該是字節), 而後2502向藍牙經過串返回數據.

 

--------------  串口log  --------------------

串口線的發送或接收, 都是基於板子命名的, 串口數據從板子出去的, 就叫發送。 串口線裏面,有一條線專門是發送的, 這條線叫發送線, 原理圖上的焊點叫tx。
t (transmit)表示發送,從板子到電腦,
r (receive)接收,從電腦到板子,接收電腦發來的命令。
原理圖上有註釋,uar1 for ap log, 從原理圖對應的pcb圖上找到測試的uart點。


串口線裏有個轉喚器, 白色線表示發送, 綠色線表示接收,黑線表示接地。 通常看串口log,  只用發送,即只連白線與黑線。 若是黑線接到了rx上,即接收點,串口log就是亂碼。

 

lk傳過disable_uart參數決定了,串口是否吐log.  若是lk後面的階段,如kernel, recover模式,若是不吐log. 就要檢查這個參數。

串口若是想吐android log, 就必須在命令行下,輸入logcat。 若是沒有這個命令, 串口是不會吐android log 的。

 

串口能夠看到初始化log, preloader, lk, 內核的,串口日誌是很是須要的。usb沒法看到初始化日誌。

pcb通常只選pads, vias兩項, 從sch對應找到pcb鐘的測試點

 

須要一個usb轉串口驅動的軟件,若是環境變量有修改,這個軟件就安裝失敗。

用secureCRT看串口log輸出:
從設備管理器上,找到端口,這裏10
鏈接速率選最大,其它默認
若是有光標,說明連上了,能夠看串口log了。


------------- 將串口註冊爲一個終端 ------------
tty_io.c 註冊tty設備

 

uart0:ap 側log
uart1: modem側log

若是不接rx拿掉,則無此問題
終端是與外部與計算機交互的一個窗口

------------------------


pty是虛擬終端,
pts, ptmx是pty的實現
每打開一個終端, /dev/pts/ 下就有一個文件


先從外部特性認識一下
一個串口(串行端口),就是一個終端,對應/dev/ttySn
在圖形界面下,打開終端實際是打開依終端,對應/dev/pts/ 下面的一個文件,能夠打開終端,看一下pts目錄下多了一個文件。
用echo "1" > /dev/pts/n 能夠看到終端下面出現相應字符。
查看當前終端, 用tty, 如可看到/dev/pts/2
對於/dev/console, 只有單用戶模式下,纔可登陸到控制檯
用who, 可看到打開了多少個虛擬終端。
/dev/tty始終表明當前終端,若是當前終端爲/dev/pts/2, 則/dev/tty/就表明/dev/pts/2
echo "1" > /dev/tty等同於 echo "1" > /dev/pts/2

ps -aux 的TTY列,顯示在哪一個終端上運行


再從代碼上分析實現:
從上層到驅動層:
tty_io.c read
線路層:tty_ldisc.c read 等待隊列機制進入睡眠
驅動層:以串口爲例,則應爲 serial_core.c


fs_initcall與module_initcall, 都是define_initcall宏函數,被放在vmlinux.lds.s連接腳本的INIT_CALLS宏指定的init段中,該宏在vmlinux.lds.h中定義。

調用過程: start_kernel-> init-> init線程函數調用do_initcalls來調用這些init函數。

字符設備初始化(drivers/char/mem.c)主要就是tty初始化,chr_dev_init->tty_init,完成tty設備初始化,總算看到字符設備的應用示例了, 設備初始化必定會建立設備模型,

--------------------
串口線中:白線爲tx, 即發送線。  綠線爲rx. 即接收線。

接上rx線,不會有機器掛掉的問題,把軟件從新firmware upgrade一下,就解決休眠後掛掉的問題,

用rx,向機器發送命令,須要機器亮屏,可以使用tab鍵,在usb線不夠用,或usb口不能用時,用rx串口, 同樣看到adb shell所能看到的文件信息,調用otg,usb被佔用,這時用串最合適。
若想看log, 能夠直接aee -k 6就顯示log.
選中後,能夠直接查找

control+f 進入debug模式, 這個模式能看到arm各寄存器的值,中斷號信息,

   

開機初始化log只能看串口,由於adb shell就內核徹底啓動後的用戶空間的一個進程,因此adb shell 看不到內核初始化的log, 這包括各個驅動的probe初始化log. mtk log創建在文件系統上,因此也沒有內核初始化log.

preloader lk 內核初始化log均可經過串口看到。 

 有亂碼時,重啓secure  uart就行了。

 

-----------   串行總線基本原理  -------------

RS-232是串行總線標準.該總線按位傳送.
串行總線由發送線tx,接收線rx,地線組成.
發送線在發送的同時,接收線能夠接收,即異步通訊
波特率是每秒傳送的位數.單位是bps. 通常一個字符有10位,1個起始位.1個結束位,8個數據位. 每秒字符數(即信息包數,一個信息包含一個字符)乘上字符的位數,便是波特率.
數據位,一個信息包有一個開始位,一個結束位.數據位有的7位,有的是8位.這個要根據協議肯定.

中止位一方面表示一個信息包的結束,一方面提供校訂同步時鐘

校驗用奇偶校驗.若是是偶校驗,數據1的個數爲偶數,校驗位就爲0. 能夠判斷是否有噪聲干擾了信號.

uart鏈接的串行設備, i2c鏈接的並行設備. 
uart通常用於計算機與外部設備的通訊,如鍵盤等. i2c通常用於內部模塊通訊.sensor都是用i2c. gps, 藍牙等射頻相關的都走串口.

顯示器也用串口,有9針串口, 也有25針串口. 

所謂協議,接收方與發送方肯定,一個信息包的每一個位表示的含義.雙方對此的理解必須是一致的.

接收過程:由波特率和接收時鐘,肯定每一位的時間長度.
當信號線從1跳到0,表示開始接收.
一偵一幀的接收. 在一幀以內,用時鐘肯定接收特定的位.
每隔8個時鐘,來接收一位.

把數據放到寄存器中,在發送時鐘的控制下,將寄存器的數據移位輸出.

在接收端,在接收上升沿的那個時刻,對數據採樣,把數據放到移位寄存器中,組成並行數據取出.

波特率是一秒鐘發送的位數.波特率因子發送或接收一個數據位須要的時鐘數. 
顯示屏25針的串口有4條數據線,11條控制線,其他備用線.

 

-----------------------------

串口也能夠同步通信, 這時須要多出一個時鐘線, 由於同步通信須要硬件上額外支持, 通常不用同步通信.

訪問串口設備文件的方法:
改變串口設備文件的權限, 以讓通常程序能夠訪問

一切皆是文件,  打開串口設備, 就中打開這個文件, 即
open("/dev/ttyS0", );

進程打開一個串口設備, 默認,進程就是這個串口設備的終端, 控制終端,  串口設備上的信號都會影響這個進程, 如ctrl+C這個信號就會終止這個進程.

若是不想接收這個串口的信號, 使進程不成爲這個串口的終端, 就不會收到串口的信號了. 用O_NOCTTY.

若是進程不關心另外一端是否鏈接,  即不關心dcd信號的狀態, 就用O_NODELAY.

向串口能夠寫入數據, 發at命令就是寫數據, 用write系統調用. 

從串口讀數據, 就是從串口緩衝區上讀數據,  若是得不到數據, read就不返回.

若是想讓read當即返回, 就要用fcntl設置一下, fcntl(fd, F_SETFL, FNDELAY);

關閉串口, 直接關閉這個設備文件便可, 就會將dtr信號拉低.

CLOCAL與CREAD, 保證程序不會成爲端口的全部者, 全部者必須處理各類信號.
options.c_cflag |= (CLOCAL | CREAD);

控制選項還可設置奇偶校驗.
沒有奇偶校驗:
options.c_cflag &= ~PARENB
options.c_cflag &= ~CSTOPB
options.c_cflag &= ~CSIZE;
options.c_cflag |= CS8;
奇數校驗:

options.c_cflag |= PARENB  // 使能校驗位
options.c_cflag &= ~PARODD
options.c_cflag &= ~CSTOPB
options.c_cflag &= ~CSIZE;
options.c_cflag |= CS7;

即c_cflag設置成7E1

偶數校驗:
options.c_cflag |= PARENB
options.c_cflag |= PARODD
options.c_cflag &= ~CSTOPB
options.c_cflag &= ~CSIZE;
options.c_cflag |= CS7;
即c_cflag設置成7O1

 

控制選項中設置了奇偶校驗,  在輸入選項就要把奇偶項剝去, 設置爲:

options.c_iflag |= (INPCK | ISTRIP);

若是發生了奇偶校驗錯誤, DEL字符和NUL字符和出錯的字符一塊兒發出.

 

若是打開了使能了奇偶校驗, 又要作一些特別試驗, 如在發生奇偶校驗錯誤, 也要忽略, 放行數據, 可用

options.c_iflag |=IGNPAR;

這時只有NUL字符送出

 

若是硬件上支持cts/rts, 就要設置:
options.c_cflag |= CNEW_RTSCTS
若是不支持:
options.c_cflag &= ~CNEW_RTSCTS;

 

舊的接口沒有c_ispeed,和c_ospeed兩個成員.  因此就用了CBAUD,B9600等波特率常數

常量TCSANOW標誌全部改變必須馬上生效而不用等到數據傳輸結束

tcsetattr 能夠設置的有:
TCSANOW標誌全部改變必須馬上生效而不用等到數據傳輸結束
TCSADRAIN  等待傳輸完以後再生效.

串口鏈接兩臺機器, 波特率應爲兩個中較小的那個.

設置一個字符大小:
options.c_flag &= ~CSIZE;
options.c_flag |= CS8; 也能夠CS8.

 

 

 

--------------------------

------------------------

相關文章
相關標籤/搜索