前言
本周筆者花了好多天的時間,計劃從多個方面對串口驅動做個比較。下面就從以下幾個角度做個對比測試。
1. 工作模式對照
2. close open 測試
3. poll 發(fā)送測試
4. flush 支持測試
5. 非阻塞收發(fā)測試
6. 阻塞收發(fā)測試
7. 回環(huán)測試數據丟失率
其它未測試項:stream 支持,因為 v1 v2 只有 poll 模式支持, serialX 可以全模式支持,這一項未進行對比。
測試環(huán)境
- rt-thread 4.1.0
- STM32F429-ATK-APOLLO
- 串口收發(fā)緩存均設定 128 字節(jié)
工作模式對照
版本 | poll收發(fā) | 阻塞/非阻塞 | 驅動層緩存 | DMA支持 | STREM 支持 |
v1 | Y | - | - | Y | 僅poll |
v2 | Y | * | Y | Y | 僅poll |
X | Y | Y | Y | Y | 全模式 |
> \* v2 對阻塞概念的認識,僅認為是降低 cpu 耗用。
close & open 測試
測試過程:
1. 先用 poll 模式打開,打開失敗直接返回;成功輸出 "POLL modeopen opened\n" 。
2. 輸出 "CLOSE & REOPEN\n" 。關閉串口設備,再用中斷收發(fā)模式打開,打開失敗直接返回;成功輸出 "INT mode opened\n" 。
3. 最后循環(huán)關閉打開 1百萬次。打開失敗直接返回。
4. 測試通過,使用 poll 模式打開串口設備,并輸出 "REOPEN successfull\n"。準備進入下一項測試。
版本 | v1 | v2 | X |
測試結果 | 通過 | 通過 | 通過 |
poll 發(fā)送測試
用 poll 模式打開串口,發(fā)送若干數據。
版本 | v1 | v2 | X |
測試結果 | 通過 | 通過 | 通過 |
flush 支持測試
如果沒有 flush ,驅動緩存的數據可能沒有完全輸出到外設,這個時候 close 設備可能出現丟失部分數據。
使用 flush 的目地就是保證驅動層緩存數據完全輸出到外設,之后對設備的任何操作不會影響之前的數據。
版本 | v1 | v2 | X |
測試結果 | 不支持 | 不支持 | 通過 |
> 因為 v1 不支持非阻塞發(fā)送,也沒有驅動層緩存,write 總是把最后一個字節(jié)寫到串口移位寄存器后才返回。所以 v1 不會出現丟失數據的現象。
> v2 在這一環(huán)節(jié)的表現和 v1 是一樣的,大家可以猜猜原因是啥。
**注:本部分為了測試 flush 特性有效性,因此 X 出現 close 的時候出現丟數現象。使用版在 close 設備的時候應該強制 flush 一下的。**
非阻塞收發(fā)測試
使用中斷非阻塞模式打開串口設備,發(fā)送 10k 左右數據量,同時測量一下時間。
數據量 | v1 | v2 | X |
102400 | 102400 / 9762ticks | 102400 / 8863ticks | 102400 / 8863ticks |
10240 | 10240 / 976ticks | 10240 / 876ticks | 10240 / 876ticks |
128 | 128 / 12ticks | 128 / 11ticks | 128 / 11ticks |
這部分測試大體上符合預期,因為有緩存,v2 和 X 先把數據放到緩存中就返回了。這樣可以減少發(fā)送等待時間。
阻塞收發(fā)測試
數據量 | v1 | v2 | X |
102400 | 102400 / 9762ticks | 102400 / 8902ticks | 102400 / 8866ticks |
10240 | 10240 / 976ticks | 10240 / 890ticks | 10240 / 884ticks |
128 | 128 / 12ticks | 128 / 11ticks | 128 / 11ticks |
> v1 在非阻塞和阻塞兩種模式下的表現是一樣的,因為它沒有阻塞概念。
>
> v2 耗時比 v1 少,這是在預料中的,但是,它還是比 X 多了幾個 tick 。這也是上文中工作模式對照部分對它的阻塞/非阻塞特性加 \* 的原因。
特別測試,當每次寫小于串口驅動層緩存大小的數據時,
數據量 | v2 | X |
16 | 1ticks | 0ticks |
32 | 5ticks | 0ticks |
128 | 11ticks | 0ticks |
為什么出現了和上面表格不一樣的結果,因為這次測試,每次寫之前有個 1s 延時,保證串口緩存是空的。**當串口緩存大小是 N 前提下,每次 write 小于等于 N 數量的數據應該可以直接寫到緩存,并立馬返回!**所以,對于 X 來說耗時就是 **0**。
這個很重要,**當我們用串口調試程序,需要打印一些信息的時候,又不希望因為串口輸出數據影響到其它業(yè)務的時序,或者,最大限度地降低因串口輸出數據而影響其它程序執(zhí)行時序**。
回環(huán)測試數據丟失率
使用阻塞模式打開串口設備。這次通過串口調試助手以 20ms 的定時間隔,發(fā)送 384 字節(jié)數據。
版本 | v1 | v2 | X |
丟失率 | 671144 / 556848/17.03% | 1208816/1070464/11.45% | 2390800/2390800/0% |
> v2 在這一步表現很差,第一次,筆者應用層緩存是 512 字節(jié),想 `rt_device_read(uart, -1, recvbuf, 512);` 發(fā)現 read 不到任何數據,read 也不阻塞了,而是總能返回,單步進去看到,但接收的數據大于驅動緩存的時候,驅動拒絕處理,直接返回0!!!v2 的缺陷之一。
>
> 鑒于以上原因,之后改成 `rt_device_read(uart, -1, recvbuf, 128);` 應用緩存和驅動緩存大小相等。
>
> 手動單次發(fā)送,一次發(fā)送 344 字節(jié)數據(多于驅動緩沖大小),接收 256 字節(jié),再次發(fā)送,接收 384 字節(jié),第三次發(fā)送接收還是 256 字節(jié),第四次又變成 384字節(jié)。
即便考慮到 v2 的上述缺陷,最多有 127 個字節(jié)數據被“滯留”串口驅動緩存里未及時返回。也彌補不了上述丟失率!
開啟 DMA 的表現
很遺憾,v1 只支持 DMA 接收不支持 DMA 發(fā)送(估計以后也用不上 v1 了),由以上對比測試我們發(fā)現 v2 和 v1 很類似,在測試 v2 DMA 接收發(fā)送時也發(fā)現總體效果和使用中斷沒多少差異。
X 的表現如何呢?等待您的發(fā)現!
> 遺憾的是,筆者對 STM32 的 HAL 極其不熟悉,又極其不想用 HAL 。花了很長時間想自己通過寄存器配置實現,最終沒成功,還是放棄了。
>
> HAL 有一個好處,那就是幾乎可以適配 STM32 所有系列芯片。但是,HAL 不是為 OS 而生的 `#error "USE_RTOS should be 0 in the current HAL release"`,在 OS 上用終究有可能遇到失鎖的問題。
>
> 使用 HAL 還有個小小的瑕疵,那就是 `is_dma_txing` 判斷變得不友好,無奈之下,筆者在 `struct stm32_uart` 中添加了個 `rt_bool_t dmaTxing;` 變量 —— ”HAL 中 gState 和 RxState 已經夠多了“ 。算是目前的一個小遺憾吧。
結束語
最后,依舊公開測試代碼,本次測試使用的代碼可以在 [serialX]( https://gitee.com/thewon/serialX ) 倉庫找到。近期,筆者也會將 serialX 提交到 rt-thread 主倉庫。
提前預告,下次我們來聊聊 serialX 在做控制臺串口時遇到的問題已經解決方案(包括使用中斷 DMA 收發(fā)模式打開的串口設備)。
相關文章:
rt-thread 驅動篇(一) serialX 框架理論
rt-thread 驅動篇(二) serialX 理論實現
審核編輯:湯梓紅
-
測試
+關注
關注
8文章
5345瀏覽量
126838 -
串口驅動
+關注
關注
2文章
82瀏覽量
18694 -
RT-Thread
+關注
關注
31文章
1299瀏覽量
40259 -
serialX
+關注
關注
0文章
7瀏覽量
808
發(fā)布評論請先 登錄
相關推薦
評論