前言
盡管仍然很多癡男怨女在 v1 v2 身上跌倒、跌倒、繼續(xù)跌倒,仍然阻止不了他們飛蛾撲火式的被 v1 v2 的缺陷所吸引而殉情。
它一如既往的保持著優(yōu)良的特性,也有可能是很多人沒發(fā)現(xiàn),主要是接受它的人很少。不過,這不影響今天它帶來新的特性。
阻塞超時(shí)
我們一直強(qiáng)調(diào),它有與之前非同一般的兩個(gè)概念“阻塞”“非阻塞”。雖然 v2 熱火朝天的提出了這兩個(gè)概念,但是實(shí)現(xiàn)的效果卻不盡人意。
在之前的正式文檔里,我沒膽量承認(rèn)一個(gè)事實(shí),那就是,阻塞讀在無數(shù)據(jù)可讀的時(shí)候?qū)⒂肋h(yuǎn)阻塞下去。某些應(yīng)用場景并不希望這樣,我們希望等待某設(shè)備響應(yīng),若干時(shí)間后無響應(yīng)超時(shí),我們返回繼續(xù)做其它工作,而不是被無響應(yīng)的設(shè)備永久占用。
給某些論壇提問里的解答時(shí),我提到過幾次 serialX 可以通過以下技術(shù)手段應(yīng)對這種場景。
方法一
使用非阻塞模式打開,超時(shí)讀過程偽代碼可能如下這樣:
while(timeout > 0) {
read
sleep 1
timeout -= 1
}
if (timeout == 0) {
// timeout here
} else {
// no timeout
}
方法二
使用完成中斷 indicate 回調(diào)函數(shù)發(fā)消息,這也是官方提供的讀串口設(shè)備的“標(biāo)準(zhǔn)”方式
static void serial_thread_entry(void parameter)
{
char ch;
while (1)
{
/ 從串口讀取一個(gè)字節(jié)的數(shù)據(jù),沒有讀取到則等待接收信號量 /
while (rt_device_read(serial, -1, &ch, 1) != 1)
{
/ 阻塞等待接收信號量,等到信號量后再次讀取數(shù)據(jù) */
rt_sem_take(&rx_sem, timeout);
}
...
}
}
注:此段代碼改編自官方文檔
大多數(shù)人第一次使用 rtt 的串口設(shè)備也是用這段代碼測試的。但是,serialX 不提倡大家使用 indicate 回調(diào)函數(shù)。
serialX 有它自己的特性,它有它自己的優(yōu)美性,那就是盡可能不給應(yīng)用層代碼帶來麻煩,不要寫太復(fù)雜難懂的邏輯,不要給應(yīng)用層引入莫名未知的后果。
我們希望在不影響不改變之前的使用的前提下,rt_device_read 能夠在預(yù)定的時(shí)間內(nèi)超時(shí)返回退出,并不是用于阻塞下去,同時(shí) rt_device_read 返回 -RT_ETIMEOUT 錯(cuò)誤碼。應(yīng)用層可以根據(jù) rt_device_read 返回值
== 0 無數(shù)據(jù)
0 有數(shù)據(jù)
< 0 有錯(cuò)誤(-RT_ETIMEOUT 超時(shí))
分別處理不同情況。
serialX 的實(shí)現(xiàn)
首先,rtdef.h 添加定義,用于設(shè)備超時(shí)配置
#define RT_DEVICE_CTRL_TIMEOUT 0x30 /**< timeout for blocking */
其次,struct rt_serial_device 添加 rt_tick_t timeout_tick; 變量,設(shè)備超時(shí)時(shí)間 tick 。
然后,rt_serial_control 函數(shù)添加超時(shí)配置宏選項(xiàng)處理
case RT_DEVICE_CTRL_TIMEOUT:
rt_tick_t timeout_tick = (rt_tick_t)args;
serial- >timeout_tick = timeout_tick;
break;
最后,在 serialX.c 文件中所有涉及到阻塞的地方(包括讀寫,不包含 flush)修改 rt_completion_wait 第二個(gè)參數(shù)為 serial->timeout_tick。并當(dāng) rt_completion_wait 返回 -RT_ETIMEOUT 時(shí)退出當(dāng)前讀寫操作返回應(yīng)用層。
注意:特別說明,我們希望一個(gè)設(shè)備以阻塞模式打開時(shí),默認(rèn)的阻塞超時(shí)時(shí)間是“永久”,所以,每次 rt_device_open 后 serialX 設(shè)定阻塞超時(shí)時(shí)間時(shí)間是 RT_WAITING_FOREVER 。如果需要指定某超時(shí)時(shí)間需要 rt_device_control(serial_dev, RT_DEVICE_CTRL_TIMEOUT, &timeout);
rt_tick_t timeout = 50;
if (rt_device_open(scpi_uart_dev, RT_DEVICE_OFLAG_RDWR
| RT_DEVICE_FLAG_INT_RX
| RT_DEVICE_FLAG_INT_TX
| RT_DEVICE_OFLAG_BLOCKING) != RT_EOK)
{
rt_kprintf("Open device: %s failedn", UART_DEV_NAME);
return;
}
rt_device_control(serial_dev, RT_DEVICE_CTRL_TIMEOUT, &timeout);
rt_ssize_t ret = rt_device_read(serial_dev, -1, &recvbuf[0], 128);
if (ret == -RT_ETIMEOUT) {
rt_device_close(serial_dev);
return;
} else {
}
這就是今天我們要講的第三種方法,相比前兩種,這種方法更優(yōu)雅些,代碼邏輯也清晰。
總結(jié)
歡迎大家入坑 serialX。
-
處理器
+關(guān)注
關(guān)注
68文章
19103瀏覽量
228825 -
回調(diào)函數(shù)
+關(guān)注
關(guān)注
0文章
87瀏覽量
11529 -
串口中斷
+關(guān)注
關(guān)注
0文章
64瀏覽量
13847 -
RT-Thread
+關(guān)注
關(guān)注
31文章
1261瀏覽量
39840 -
serialX
+關(guān)注
關(guān)注
0文章
7瀏覽量
800
發(fā)布評論請先 登錄
相關(guān)推薦
評論