99久久全国免费观看_国产一区二区三区四区五区VM_久久www人成免费看片中文_国产高清在线a视频大全_深夜福利www_日韩一级成人av

程序小白
認證:優質創作者
所在專題目錄 查看專題
小小調度器——調度器核心的純C實現
小小調度器——原來C代碼還能這么寫,原作者沒少挨打吧!
小小調度器——開局default,優雅總藏于細節之中
作者動態 更多
基于stm32采用PWM驅動伺服控制器學習筆記
05-13 15:25
基于STM32驅動TM1638學習筆記——軟件篇
04-19 12:42
基于TM1638驅動8位數碼管設計分享
02-24 11:26
RT-Thread驅動之路: Studio創建FAL分區⑤
01-02 08:30
RT-Thread驅動之路: Studio 掛載通用SPI flash④
2024-12-23 13:41

小小調度器——原來C代碼還能這么寫,原作者沒少挨打吧!


開局分割線(理解了以后的一番感概):一個很偶然的機會接觸到了一個全部用C語言寫的任務調度框架,剛開始覺得有點奇怪,因為當你用它創建任務的時候,不能用switch 不能用return,局部變量還得變成static,想想寫代碼就有點別扭,深入學習了一下,的確很有意思,對RTOS的機制實現的理解,忽而有種推門而入的感覺。


好多童鞋剛入門單片機變成,還在裸跑階段的時候,對調度器三個字可能一頭霧水,這玩意兒到底干嘛用的,舉個例子,寫個led點燈的函數:

int func(void)
{
	led1_on;			//實現led1燈亮
	delayms(500);	    //延時500ms,阻塞的方式
	led1_off;			//實現led1燈滅
}

這里引入了一個阻塞的概念,對應的還有一個詞叫做非阻塞,關鍵就是延時500ms,那么執行到這個函數的時候,程序不會繼續執行,需要等待500ms:

      非阻塞的方式,程序一直等在這,等到500ms實現到了,繼續執行關燈。

      阻塞的方式,程序會記錄下當前函數的運行位置,然后跳走去執行別的函數,當500ms時間到時,再從別的位置調到該函數led1_off這一條繼續執行,而不是從函數頭部位置開始執行。

      裸機也能解決這個問題,但是要引入不少復雜的語法操作,這僅僅是一個函數的操作,一個程序不可能只有一個點燈的任務,還會有多個任務,當我們把裸機執行的操作抽象出來解決大部分問題的時候,小小調度器就出現了(他并不是很復雜的東東,其實最初的它只是為了解決一個阻塞式的delayms)。


unsigned short task0()
{
  _SS  //宏定義
  while(1)
  {
    WaitX(50); //宏定義
    LED0=!LED0;
  }
  _EE //宏定義
}

要實現阻塞,執行WaitX(50);時跳出task0任務,當50個ticket到了以后,進入函數從LED0=!LED0開始執行,最關關關鍵(重要的事兒重復三遍)的就是這三個宏:

//任務頭
#define _SS static U8 _lc=0; switch(_lc){default:

//等待X個時鐘周期
#define WaitX(tickets)  do { _lc=(__LINE__%255)+1; return (tickets) ;case (__LINE__%255)+1:;} while(0);

//任務尾
#define _EE ;}; _lc=0; return TICKET_MAX;

單看每一行都無法讀懂,不要擔心,只要記住三行注釋就可以了,接下來把他帶進去展開后我們再來看這個函數:

unsigned short task0()
{
  static unsigned char _lc=0; 
  switch(_lc)
  {
    default://注意,其實這里用 switch(_lc){case 0: 也是一樣的。
		  while(1)//死循環
		  {
				    do 
				    { 
				         _lc=(__LINE__%255)+1; //記憶當前行號
				         return 50 ; //函數返回,級任務0退出,任務主動釋放 CPU。50是WaitX(50)的參數50。
				         case (__LINE__%255)+1://當 500 毫秒過去后,會再次進入 task0 任務函數,執行task0的switch(_lc),那么 switch 會去找 case101 的代碼。即此行。
				         ;
				    } while(0);//只執行一次的循環
				    LED0=!LED0;
		  } ;
  }; 
  _lc=0;
  return 65535;
}

這看起來,總算像是一個完整的函數了,但是看到switch條件判斷被打散分布在程序里,第一感覺還是難以接受,default里面居然套上了case!!!,我們自己寫代碼如果這么寫,估計會被領導打,但是站在編譯器的角度來看,還是符合規則的,就是能完整執行。

接下來看他的執行流程,假如任務被調用,則從頭開始執行,_lc為0,所以執行default,這里把(__LINE__%255)+1當作一個常數,例如用100代替,那么接著執行return 50;函數執行結束了,這個50會返回給一個很特殊的定時器任務,執行50個tickets以后,再次主動調用task0,從case 100開始執行,led燈翻轉,然后回到while(1) 執行return50 跳走,整兒流程就是間隔50個tickets 翻轉LED輸出。

最后不得不感嘆雖然有點亂,但是的確神奇的完成了想要的工作,好像是程序里面寫了兩個bug,然后來了個負負得正,居然跑起來了~!!!

聲明:本內容為作者獨立觀點,不代表電子星球立場。未經允許不得轉載。授權事宜與稿件投訴,請聯系:editor@netbroad.com
覺得內容不錯的朋友,別忘了一鍵三連哦!
贊 5
收藏 7
關注 151
成為作者 賺取收益
全部留言
0/200
成為第一個和作者交流的人吧
主站蜘蛛池模板: 亚洲成人免费视频在线 | 欧美老熟妇乱子 | 最新看片国产精品免费在线 | 欧美性xxxxx极品 | 综合视频在线 | 免费超级淫片日本高清视频 | 性猛交╳XXX乱大交 精品国产不卡 | 国产久免费热高清视频在线观看 | 美女大胆作爱全过程 | 蜜桃免费在线视频 | 正在播放国产对白孕妇作爱 | 一级片黄色一级片 | 爆乳放荡的女教师bd | 46集连续剧免费观看 | 亚洲中文字幕久久精品无码va | 国产精品三级在线观看无码 | 免费无码中文A级毛片 | 亚洲一区欧美一区 | 中文字幕乱码亚洲精品一区 | 免费成人午夜视频 | 欧美色精品vr | 国产三级网 | 亚州av在线播放 | 亚洲视频一二区 | 最新国产一区二区 | 亚洲国产精品视频一区二区 | 欧美18videosex性欧美tube1080 | 国产91xxx在线观看大全 | 无遮无挡爽爽免费视频 | 青青草91久久久久久久久 | 久久久久亚洲一区二区三区 | 国产伦理精品一区二区三区观看体验| 99久久久无码国产精品古装 | 久久女人精品 | 久色欧美| 一级片精品 | 久久99日韩国产精品久久99 | 乱人伦中文视频在线观看 | 人人鲁免费播放视频 | 年轻的老师4 | 欧美日韩中文字幕在线 |