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

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

状态机——protothreads

發(fā)布時(shí)間:2023/12/20 编程问答 47 豆豆
生活随笔 收集整理的這篇文章主要介紹了 状态机——protothreads 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

狀態(tài)機(jī)——Protothreads


宗旨:技術(shù)的學(xué)習(xí)是有限的,分享的精神是無(wú)限的。


一、prothreads的優(yōu)缺點(diǎn)

優(yōu)點(diǎn):

??? 1. 以純C語(yǔ)言實(shí)現(xiàn),無(wú)硬件依靠性;因此不存在移植的困難。

??? 2. 極少的資源需求,每個(gè)Protothread僅需要2個(gè)額外的字節(jié);

3. 支持阻塞操縱且沒(méi)有棧的切換。

缺點(diǎn):

??? 1. 函數(shù)中不具備可重入型,不能使用局部變量;

??? 2. 按順序判斷各任務(wù)條件是否滿足,因此無(wú)優(yōu)先級(jí)搶占;

3. 任務(wù)中的各條件也是按順序判斷的,因此要求任務(wù)中的條件必須是依次出現(xiàn)的 protothread的阻塞機(jī)制:在每個(gè)條件判斷前,先將當(dāng)前地址保存到某個(gè)變量中,再判斷條件是否成立,若條件成立,則往下運(yùn)行;若條件不成立,則返回。

?

二、注意事項(xiàng)

注意:
(1)任務(wù)中使用的變量應(yīng)為靜態(tài)變量
(2)線程內(nèi)不能使用純 while(1)--即含 PT_WAIT_UNTIL()等宏的 while(1)是可以的。
不能在 switch(){case…}中調(diào)用任務(wù) Protothreads API 帶有 case 的語(yǔ)句(即只能單向嵌套)。
(3)線程內(nèi)可以使用:
for(){…}
switch(){case…}-- case 與 case 之間必須是一個(gè)完整的語(yǔ)句或者語(yǔ)句段
if(){…}else{…}
含宏的 while(1){…}
(4)ProtothreadS 系統(tǒng)可以仍然還是個(gè)大 while(1)循環(huán)。但也可設(shè)計(jì)為根據(jù)定時(shí)器產(chǎn)生的恒定間隔的中斷來(lái)觸發(fā)和管理任務(wù)
--時(shí)間觸發(fā)方式的嵌入式系統(tǒng),此時(shí)可更改 pt 結(jié)構(gòu)體為(見(jiàn)《時(shí)間觸發(fā)模式下的 ProtothreadS 設(shè)計(jì)應(yīng)用》):
struct pt

{

lc_t lc;

unsigned short count; // 每次中斷都減 1

unsigned short load; // 初始計(jì)數(shù)值

char ready; // 任務(wù)就緒標(biāo)志

}
(5)在 ProtothreadS 系統(tǒng)中延時(shí):
1)如果 ProtothreadS 系統(tǒng)是基于時(shí)間觸發(fā),則延時(shí)可基于該觸發(fā)--即基于系統(tǒng)時(shí)鐘。
2)如果 ProtothreadS 系統(tǒng)中無(wú)系統(tǒng)時(shí)鐘,
(6)Protothreads 雖然提供了在各自線程內(nèi)的條件阻塞機(jī)制,但對(duì)于在該線程內(nèi)調(diào)用的其它函數(shù),則無(wú)法阻塞其運(yùn)行。所以,
如果要在線程內(nèi)調(diào)用占用時(shí)間較多的函數(shù),為保證各個(gè)線程的實(shí)時(shí)性要求,需要將這類函數(shù)進(jìn)一步劃分為更小的函數(shù),分步執(zhí)
行。
(7) Protothread 的精華:當(dāng) Protothread 程序運(yùn)行到 PT_WAIT_UNTIL 時(shí),判斷其運(yùn)行條件是否滿足,若不滿足,則阻塞。
Protothread 的阻塞其實(shí)質(zhì)就是函數(shù)返回。
Protothread 僅能在程序員指定位置阻塞。

?

三、protothreads各函數(shù)簡(jiǎn)要介紹

函數(shù)

說(shuō)明

PT_INIT(pt)

初始化任務(wù)變量,只在初始化函數(shù)中執(zhí)行一次

PT_BEGIN(pt)

啟動(dòng)任務(wù)處理,放在函數(shù)開(kāi)始處

PT_END(pt)

結(jié)束任務(wù),放在函數(shù)的最后

PT_WAIT_UNTIL(pt,condition)

條件成立,執(zhí)行下面的;否則退出,下次直接跳到此處執(zhí)行

PT_WAIT_WHILE(pt, condition)

類似PT_WAIT_UNTIL,只是條件取反了

PT_WAIT_THREAD(pt, thread)

等待一個(gè)子任務(wù)執(zhí)行完成

PT_SPAWN(pt, child, thread)

新建一個(gè)子任務(wù),并等待其執(zhí)行完退出

PT_RESTART(pt)

重新啟動(dòng)某個(gè)任務(wù)執(zhí)行

PT_EXIT(pt)

任務(wù)后面的部分不執(zhí)行,直接退出重新執(zhí)行

PT_YIELD(pt)

鎖死任務(wù)

PT_YIELD_UNTIL(pt, condition)

鎖死任務(wù)等待條件成立重新執(zhí)行

?

四、protothreads代碼

struct pt {lc_t lc; };#define PT_WAITING 0 #define PT_YIELDED 1 #define PT_EXITED 2 #define PT_ENDED 3#define PT_INIT(pt) LC_INIT((pt)->lc)#define PT_THREAD(name_args) char name_args#define PT_BEGIN(pt) { char PT_YIELD_FLAG = 1;LC_RESUME((pt)->lc)#define PT_END(pt) LC_END((pt)->lc);PT_YIELD_FLAG = 0; \PT_INIT(pt); return PT_ENDED; }#define PT_WAIT_UNTIL(pt, condition) \do { \LC_SET((pt)->lc); \if(!(condition)) { \returnPT_WAITING; \} \} while(0)#define PT_WAIT_WHILE(pt, cond) PT_WAIT_UNTIL((pt), !(cond))#define PT_WAIT_THREAD(pt, thread)PT_WAIT_WHILE((pt), PT_SCHEDULE(thread))#define PT_SPAWN(pt, child, thread) \do { \PT_INIT((child)); \PT_WAIT_THREAD((pt), (thread)); \} while(0)#define PT_RESTART(pt) \do { \PT_INIT(pt); \returnPT_WAITING; \} while(0)#define PT_EXIT(pt) \do { \PT_INIT(pt); \returnPT_EXITED; \} while(0)#define PT_SCHEDULE(f) ((f) < PT_EXITED)#define PT_YIELD(pt) \do { \PT_YIELD_FLAG = 0; \LC_SET((pt)->lc); \if(PT_YIELD_FLAG == 0) { \returnPT_YIELDED; \} \} while(0)#define PT_YIELD_UNTIL(pt, cond) \do { \PT_YIELD_FLAG = 0; \LC_SET((pt)->lc); \if((PT_YIELD_FLAG == 0) || !(cond)) { \returnPT_YIELDED; \} \} while(0)

五、舉例

//解碼

static char camera_rs485_rx_decode(struct pt *pt, uint8_t c) {PT_BEGIN(pt);PT_WAIT_UNTIL(pt, 0x7E == c);camera_rs485.rx_count = 0;while(1){PT_YIELD(pt);if (0x7E== c){if(camera_rs485.rx_count){camera_rs485_dispatch(camera_rs485.rx_buf,camera_rs485.rx_count);PT_EXIT(pt);}else{continue;}}if(0x1B ==c){PT_YIELD(pt);if (0x00== c){c =0x1B;}else if (0x65 == c){c =0x7E;}else{//c ^=0x20;}}if(camera_rs485.rx_count < CAMERA_RS485_RX_BUF_SIZE){camera_rs485.rx_buf[camera_rs485.rx_count++] = c;}else{PT_EXIT(pt);}}PT_END(pt); }

// 模塊類型識(shí)別——定時(shí)器 static char gps_probe(struct pt *pt, uint32_t ms) {staticuint32_t tmo = 0;static inti;const char*cmd;if (tmo >ms){tmo -= ms;}else{tmo = 0;}PT_BEGIN(pt);tmo = 3000;PT_WAIT_UNTIL(pt, (0 == tmo));if(GPS_MODULE_TYPE_UNKNOWN == gps.module_type){for(i =GPS_MODULE_TYPE_UNKNOWN + 1; i < GPS_MODULE_TYPE_COUNT; ++i){if(gps_cmds[i].query_version){debug("gps_probe type: %d cmd: %s", i,gps_cmds[i].query_version);// 發(fā)送兩次,確保模塊接收到正確的命令cmd =gps_cmds[i].query_version;UartSend(gps_uart, cmd, strlen(cmd));PT_YIELD(pt);cmd =gps_cmds[i].query_version;UartSend(gps_uart, cmd, strlen(cmd));// 等待模塊輸出版本信息tmo =3000;PT_WAIT_UNTIL(pt, (0 == tmo));}if(GPS_MODULE_TYPE_UNKNOWN != gps.module_type){break;}}}// stopPT_WAIT_UNTIL(pt, FALSE);PT_END(pt); }


創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎(jiǎng)勵(lì)來(lái)咯,堅(jiān)持創(chuàng)作打卡瓜分現(xiàn)金大獎(jiǎng)

總結(jié)

以上是生活随笔為你收集整理的状态机——protothreads的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

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