找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 4673|回復(fù): 14
打印 上一主題 下一主題
收起左側(cè)

uCOS-III學(xué)習(xí)筆記

  [復(fù)制鏈接]
跳轉(zhuǎn)到指定樓層
樓主
ID:7209 發(fā)表于 2021-2-19 20:43 | 只看該作者 回帖獎(jiǎng)勵(lì) |倒序?yàn)g覽 |閱讀模式
為什么要學(xué)習(xí)這個(gè)ucos ii  
在單片機(jī)的世界里翱翔了好多年,
一直覺得無所不能、無所不會(huì)鄙視一些應(yīng)用層的開發(fā),
輕示一些軟硬都好搞一點(diǎn)的過去,
直到遇見你 ucosii 或你的好兄弟iii 我從沒有如此卑微的如此靠近過。
你是來團(tuán)結(jié)這些”地方武裝勢力的”真真為社會(huì)主義事業(yè)而奮斗終身的。
崇拜了無數(shù)大嬸,還是俺叔給我說 “ 算法” 才是 ----葵花寶典
   但有天碰到一個(gè)“事情”需要兩個(gè)或三個(gè)或更多個(gè)家庭來合力完成一項(xiàng)工作的情況下;
 比如“苦逼的程序員終于要結(jié)婚了”這就需要二個(gè)最最重要的兩個(gè)高級任務(wù)你和你老婆、
 兩個(gè)稍低一點(diǎn)的有可能存在“翻轉(zhuǎn)任務(wù)優(yōu)先級”的情況影響你和你老婆的任務(wù)執(zhí)行的”任務(wù)” ,
。ㄆ鋵(shí)我想說的是彩禮可能把好好的任務(wù)給攪黃,相當(dāng)于最高級別的優(yōu)先級丈母娘,一票否決權(quán)
 。∪绻钤缒阍谶M(jìn)行任務(wù)留有debug 的話,這些都是小菜---你懂的)
 還需要一些處理各種額外的功能任務(wù)。
   如果是單片機(jī)的“世界中”這樣的情況下需要先初始化了
  老婆的“包括找到老婆+熟悉老婆各種配件+熟悉她的各種關(guān)系”,
  初始化娶老婆的各種條件”買車+買房+買家具+++++”,
  初始化婚禮的各種瑣事,初始化她父母+你父母的各種要求;
  最后的循環(huán)執(zhí)行就是你和你老婆結(jié)婚+重復(fù)瑣事+賺錢+養(yǎng)育孩子+照顧父母+孩子結(jié)婚+自己老去,
  最后你的主函數(shù)終于運(yùn)行完畢。
  這里可能有些初始化條件不合適還有可能會(huì)出現(xiàn)#if………#else……….   //重新選擇老婆
也可能會(huì)出現(xiàn)
Do{………..}while(條件) //試婚
也可能會(huì)出現(xiàn)
Delay(10year);  //  //延時(shí)
也可能會(huì)出現(xiàn)
While(各種可能情況)
{…………..};  //這里就是一個(gè)牢籠直至…………
最危險(xiǎn)的不能進(jìn)入“迭代的” 的循環(huán)中,
一旦進(jìn)入后果無法設(shè)想
思想指針可以來回游走
可別忘記自己的類型和安全返回
否則很容易帶回的是錯(cuò)誤的數(shù)據(jù)和丟失自己,
損壞主函數(shù)的生命周期
“忒復(fù)雜了為了結(jié)一個(gè)婚這大工程還是給了系統(tǒng)好把”
系統(tǒng)是如何來處理
建立幾個(gè)任務(wù)
任務(wù)一負(fù)責(zé)各種婚前準(zhǔn)備
  任務(wù)二負(fù)責(zé)老婆家各種需要準(zhǔn)備工作
  任務(wù)三負(fù)責(zé)各種意外情況處理
  任務(wù)四負(fù)責(zé)……..
  任務(wù)五負(fù)責(zé)……….
  任務(wù)六…………
這樣是不是稍微輕松一下,但是也不是最輕松的
系統(tǒng)給設(shè)定好了各種格式
現(xiàn)在的社會(huì)你只需要有錢就可以了

Ucos  ii  -----   iii    也一樣

感覺好幸福
有中馬上見到美麗賢惠聰明可愛的 新娘子
流會(huì)兒口水了

評分

參與人數(shù) 2黑幣 +62 收起 理由
gracture + 12 贊一個(gè)!
admin + 50 共享資料的黑幣獎(jiǎng)勵(lì)!

查看全部評分

分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏4 分享淘帖 頂2 踩
回復(fù)

使用道具 舉報(bào)

沙發(fā)
ID:7209 發(fā)表于 2021-2-19 21:57 | 只看該作者
首先,第一個(gè)要解決的問題是,
為什么我們需要uCos?就像最開始學(xué)C編程時(shí),師傅告訴我們,指針很重要,那時(shí)你肯定有一個(gè)大的疑問,指針到底有什么好?
心里一直犯嘀咕著:不用指針不一樣把程序編出來了?  現(xiàn)在想想看c語言沒了指針,是不是寸步難行呢。回到正題,我們到底為什么需要uCos?

一般的簡單的嵌入式設(shè)備的編程思路是下面這樣的:
int  main ()
{     //初始化各種外設(shè)
    //初始化各種時(shí)鐘
    //初始化IO 口
   
  while(1)
  {
    {處理事務(wù)1};
    {處理事務(wù)2};
    {處理事務(wù)3};
        .......
    {處理事務(wù)N};
   }
}

void  shijian1 ()
{}
void shijian2()
{}
void shijian3()
{}

isr_server
{
    {處理中斷};
}

這也是我們在51、 STM32、AVR、stm8 中最常用的形式
這是最一般的思路,對于簡單的系統(tǒng)當(dāng)然是夠用了,
但這樣的系統(tǒng)實(shí)時(shí)性是很差的,
比如“事務(wù)1”如果是一個(gè)用戶輸入的檢測(掃描按鍵是否有按下),
當(dāng)用戶輸入時(shí),
如果程序正在處理事務(wù)1下面的那些事務(wù),
也就是在處理任務(wù)2 后任務(wù)3 后任務(wù)4。
那么這次用戶輸入將失效,
用戶的體驗(yàn)是“這個(gè)按鍵不靈敏,
這個(gè)機(jī)器很慢”,
而我們?nèi)绻咽聞?wù)放到中斷里去處理(我們把按鍵掃描放在中斷函數(shù)里面),
雖然改善了實(shí)時(shí)性但會(huì)導(dǎo)致另外一個(gè)問題,
有可能會(huì)引發(fā)中斷丟失,
(這里我沒有想明白 按鍵掃描在中斷里丟失 是不是順序掃描0-9個(gè)按鍵
當(dāng)掃描到按鍵8 ,而這個(gè)時(shí)候 我 按得失2,
如果中斷掃描足夠快的話,應(yīng)該也很快就可以掃描到
)
這個(gè)后果有時(shí)候比“慢一點(diǎn)”更加嚴(yán)重和惡劣!
又比如事務(wù)2是一個(gè)只需要1s鐘處理一次的任務(wù),
那么顯然事務(wù)2會(huì)白白浪費(fèi)CPU的時(shí)間。
通篇想說就是 “實(shí)時(shí)性不夠好”





評分

參與人數(shù) 1黑幣 +20 收起 理由
admin + 20 回帖助人的獎(jiǎng)勵(lì)!

查看全部評分

回復(fù)

使用道具 舉報(bào)

板凳
ID:7209 發(fā)表于 2021-2-20 16:28 | 只看該作者
下面不是重點(diǎn)
  有些書會(huì)介紹(前后臺系統(tǒng)   +  實(shí)時(shí)內(nèi)核)都是用于處理實(shí)際工業(yè)具體問題的軟件編程方法,
  前后臺系統(tǒng)結(jié)構(gòu): 就是一個(gè)死循環(huán)和若干個(gè)中斷服務(wù)程序
中斷用于處理系統(tǒng)的異步事件(前臺)
相應(yīng)函數(shù)完成相應(yīng)的操作(后臺)
這其實(shí)和我們平常寫的一樣,主函數(shù)+應(yīng)用函數(shù)+中斷,只不過我們沒有給他起名字而已。
這樣做的有一個(gè)弊端也是書上說的,后來我想想也對啊
如果中斷時(shí)前臺――― 
 為了保證任務(wù)得到及時(shí)處理,
 哪些本該在任務(wù)中執(zhí)行的關(guān)鍵代碼必須放在,中斷里執(zhí)行。
。ň褪菫榱说玫郊皶r(shí)的響應(yīng))
 想想中斷到可以及時(shí)處理特定的數(shù)據(jù)并且更新
而任務(wù)或應(yīng)用程序是不是能立刻更新吶???
這個(gè)真未必能夠及時(shí)執(zhí)行。
比如:
一個(gè)項(xiàng)目是這樣的定時(shí)開燈或關(guān)燈+WIFI 通信 + 時(shí)間屏幕顯示
更新時(shí)間功能我們放在中斷里
當(dāng)進(jìn)行WIFI 通訊 時(shí)
即時(shí)我讀取到了時(shí)間改變了,但是現(xiàn)在沒有切換到
屏幕時(shí)間顯示,是不是也不會(huì)更新顯示時(shí)間數(shù)組
(這個(gè)說法有些澀)
生活的例子:
現(xiàn)在需要燒水(設(shè)定一個(gè)時(shí)間)+看閨女
看閨女就是中斷里的代碼
燒水開了沒有開,只有看2分閨女――― 去看看時(shí)間或水―――
燒水時(shí)間是一值在走并且水一直在升溫
而作為主循環(huán)中每走幾分鐘才查看一回,而且這個(gè)查看時(shí)間還不固定
閨女哭了、閨女不讓走、閨女要吃奶粉
這些在中斷中都需要立即執(zhí)行的
中斷里――只有聽見水壺鳴叫或時(shí)間到
才去處理燒開水灌進(jìn)水壺里的動(dòng)作
有個(gè)說法 “任務(wù)級響應(yīng)延遲”
實(shí)時(shí)內(nèi)核:(ucos)
用于管理控制器、微處理器的時(shí)間及硬件資源的軟件代碼。
忒重要了這句話,就是通過管理控制器的時(shí)間來控制硬件資源的軟件代碼;
通過把一個(gè)大的項(xiàng)目分解成為幾個(gè)小的任務(wù)或叫線程
分配單片機(jī)的時(shí)間來間隔運(yùn)行任務(wù) 1、2、3、4、5
每個(gè)任務(wù)都是的
while(1) { ;;;}這樣的死循環(huán)
實(shí)時(shí)內(nèi)核--- 相當(dāng)于家長來負(fù)責(zé)管理這些任務(wù)的運(yùn)行時(shí)間、運(yùn)行順序;

評分

參與人數(shù) 1黑幣 +20 收起 理由
admin + 20 回帖助人的獎(jiǎng)勵(lì)!

查看全部評分

回復(fù)

使用道具 舉報(bào)

地板
ID:7209 發(fā)表于 2021-2-20 16:54 | 只看該作者
重點(diǎn)一句話:    ucos是用約70多個(gè)新函數(shù)形式為應(yīng)用程序代碼提供服務(wù)的。   這句話也是書上的,相當(dāng)于學(xué)習(xí)“c 語言中的 頭文件函數(shù)”;   我們想 用 vc6.0  在屏幕上輸出 字符 是不是要用到printf() ,   而用到這個(gè)函數(shù)是不是需要 #include <stdio.h>   想輸出時(shí)間 是不是需要 #include <ctime.h>   學(xué)習(xí)細(xì)節(jié)---( 時(shí)刻把握整體  我們 wifi.c + LED.C + KEY.C               都寫好了,并且放在一個(gè)工程中了, 調(diào)用一下系統(tǒng)函數(shù)              來協(xié)調(diào)外設(shè)給我老實(shí)工作否則,              在現(xiàn)在的 while(1) {} 死循環(huán)中,一樣也能干掉你這個(gè)線程)   不畏懼困難。 還有這個(gè)線程就是任務(wù)就是一個(gè)函數(shù)實(shí)現(xiàn)一個(gè)功能。

評分

參與人數(shù) 1黑幣 +20 收起 理由
admin + 20 回帖助人的獎(jiǎng)勵(lì)!

查看全部評分

回復(fù)

使用道具 舉報(bào)

5#
ID:7209 發(fā)表于 2021-2-25 16:23 | 只看該作者
從總體上理解一個(gè)事物
從總體上看待一個(gè)人
從總體上學(xué)習(xí)一個(gè)技能
這個(gè)總體很重要,比如學(xué)習(xí)ucos  iii 或 ii
其實(shí)如果從總體上說沒啥大的區(qū)別
可也不能說沒有區(qū)別  
先學(xué)會(huì)一個(gè)在說 III 和 II 都是個(gè)浮云
先白話幾句  下面都是聊天
如果計(jì)劃作一件事情是不是先在腦子里思考一下這個(gè)事情的大概,
如果有老婆的話是不是需要和老婆商量一下,如果商量好了或自己決定了這件事情;
就相當(dāng)于 建立了 “任務(wù)” 現(xiàn)在建立了任務(wù)
    這個(gè)任務(wù)可能是一個(gè) “看電視的閑任務(wù)”
也可能會(huì)遇到更緊急的任務(wù) “只好刪除這個(gè)任務(wù)” ( 更緊急的任務(wù)是優(yōu)先級)
還有可能 “在開始操作這個(gè)任務(wù)的時(shí)候先掛起這個(gè)任務(wù)”(就是先記下來不執(zhí)行)
頂下來的無論學(xué)習(xí)任務(wù)還是找老婆的任務(wù)一旦定下來就必須要有回應(yīng)
哪怕是 個(gè)“空任務(wù)”什么也不做; 也要對他有定義有設(shè)置。

人生就和這個(gè)很類似
china main()  //中國出生  也就是建立了任務(wù)
{
   father_init(); // 父親初始化
   mother_init(); // 母親初始化
   house_init();  //房子初始化
   while(1)
   {
     幼兒() ;  //
     小學(xué) ();  //
     中學(xué) ();  //
     高中 () ; //
     大學(xué) ();  //
     工作 ();  //
     組合家庭 () ; //
     生活 ();  //
     孕育新生命 ();  //  ------------------   china main()
     50_year(); //                            {  ;;;;;;;;
     60_year(); //                              }
     70_year(); //
     80_year(); //
     90_year(); //
     over_game(); //      
    // 刪除任務(wù)本身 (); //
     // 每個(gè)人沒有 return
     //
   }
}
-----------------------------------------------
china main()
{
   //
   OSInit(&err);    //  各種適齡婚前的必要條件

   OSTaskCreate("new_family");  // 創(chuàng)建一個(gè)新任務(wù) 創(chuàng)建新的家庭

   OSStart(&err);   //這個(gè)開始任務(wù)有些 “農(nóng)村分家的意思”   

  }

static void new_family()
  {
      //各種初始化兩個(gè)人新家的準(zhǔn)備
     //各種初始化條件

     OS_CPU_SystickInit();   //時(shí)鐘 控制一個(gè)家庭的節(jié)奏
     Mem_Init();    //初始化家庭的內(nèi)存空間

    CPU_IntDisMeasMaxCurReset();  //復(fù)位清 零當(dāng)前最大 夫妻吵架互相不搭理的 最大隔閡時(shí)間
    //其實(shí)這里 不寫函數(shù)名字好一些
    //提前給大家提高了  困難  指數(shù)

// ( 只看注釋也可以)

     OSTaskCreate( " father_taks");    //

     OSTaskCreate( " mother_task");    //

     OSTaskCreate("  girl_task");     //

     OSTaskCreate("  son_task");      //


     OSTaskDel("&newfamily ,&err");  //刪除開始任務(wù)
   }



void father_task1()
  {          }
void mother_task2()
  {          }
void girl_task()
   {              }
void son_task()
  {                }

主要任務(wù)就是這四個(gè)方面還有別的比如 :

  給父母養(yǎng)老_task ();   // 其實(shí)這個(gè)也是應(yīng)該添加在任務(wù)里的
在往后的 幾十年里 這四個(gè)任務(wù)會(huì) 按照一定的 "cnts" 或 Systick  系統(tǒng)時(shí)鐘穩(wěn)定運(yùn)行

  我們是生活在一個(gè)連環(huán)的任務(wù)中,我們是父母的任務(wù)也是自己的孩子的任務(wù),
  這要在C++ 上是繼承和被繼承的關(guān)系是類和派生類的關(guān)系
  在 代碼中我們就是一個(gè)任務(wù),一個(gè)家庭是一個(gè)大任務(wù);
  丈夫_apptask();
  妻子_apptask();
  孩子_apptask();
  閨女_apptask();
  分工不同,需要完成的任務(wù)也不同
  但是在 社會(huì)這個(gè)大循環(huán)中個(gè)體所賦予的任務(wù)大同小異
  分工不同造成實(shí)際需要完成的工作也不同
  比如:father_init() ; 這個(gè)初始化函數(shù)中就必須表現(xiàn)出掙錢的特征,
     或者說以這個(gè)為主要任務(wù)
  //其實(shí)也就是下面的 括號里的 具體名字 ,叫法不同 我覺得來表示人生還是很像的
(  III 將學(xué)習(xí) 任務(wù) --- 任務(wù)時(shí)間片運(yùn)行 --- 閑任務(wù)和阻塞延時(shí) --- 時(shí)間戳 --- 臨界段
  --- 就緒列表 --- 優(yōu)先級 --- 時(shí)基列表 --- 時(shí)間片 --- 任務(wù)掛起和恢復(fù) --- 任務(wù)刪除



評分

參與人數(shù) 1黑幣 +20 收起 理由
admin + 20 回帖助人的獎(jiǎng)勵(lì)!

查看全部評分

回復(fù)

使用道具 舉報(bào)

6#
ID:7209 發(fā)表于 2021-3-1 21:40 | 只看該作者
下面繼續(xù)閑聊,
  經(jīng)過幾個(gè)片斷聊天理解ucos  也是不現(xiàn)實(shí)的。
  如果是趙大爺?shù)脑捑褪?“話療”,
  通過談話的 方式來理解明白我們需要掌握的東西.

  剛開始學(xué)習(xí)ucos 時(shí)也是膽戰(zhàn)心驚苦悶無比,
  搞不懂為什么有些通俗易懂的知識非要寫的那么高大上
  難以理解。
  現(xiàn)實(shí)社會(huì)這個(gè)大循環(huán)中,人們是圍繞 “錢” 在轉(zhuǎn),
  無論多少個(gè)家庭、個(gè)人都無法離開這個(gè) 最基本的 生存需求,
  不圍繞錢來 轉(zhuǎn)的 我只能想到 “佛” “道” 界,
  這些如果在 ucos 系統(tǒng)中,我理解應(yīng)該就屬于 "空閑任務(wù)" 沒有這些任務(wù)是不行的。
  ( 社會(huì)需要這些精神上的知識)

  既然 社會(huì) 是圍繞 "錢" 這個(gè)最基本的目標(biāo)在運(yùn)作,
  那么 在ucos 中 有沒有 也有一個(gè)也圍繞 “靶點(diǎn)”而運(yùn)行?
  通過學(xué)習(xí) 知道是有的;
  這個(gè) 點(diǎn)就是 “時(shí)鐘”--- Systick --- 類似---心跳--
  在ucos 系統(tǒng)中也是圍繞這個(gè)和錢類似的  "點(diǎn)" ,
  讓任務(wù)來有條不紊的運(yùn)行,  沒有他行不行,萬萬不行。
  在學(xué)習(xí)單片機(jī)的時(shí)候也有 51、avr 、stm8、stm32、PIC。
  這些都是需要時(shí)鐘的;
  現(xiàn)在32 特別火 就已32 來說吧!

下面不是閑聊需要理解的  
  stm32 中有一個(gè)SysTick定時(shí)器 他是一個(gè)24位倒計(jì)定時(shí)器,當(dāng)計(jì)數(shù)到 0 時(shí),
  則從reload 寄存器中自動(dòng)重新裝載定時(shí)器的初值,并開始新一輪的計(jì)數(shù)。
  這個(gè)定時(shí)器是24位
  這個(gè)定時(shí)器是倒計(jì)時(shí)(比如 從1000減到0 , 1000 就是初值 )
  當(dāng)遞減到0 時(shí)就有從 reload 寄存器中重新加載初值
  這個(gè)初值最大是多少 24位 = 0xffffff = 0b1111 1111 1111 1111 1111 1111
  2^24 = 等于多大的數(shù)值 =  16777215
  一般我們也沒有用這么大的,這是可以加載的最大數(shù)值
  也就是數(shù) 數(shù)字來 cpu 也要倒序 減 - - ;
  在 ucos 中使用systick 來計(jì)數(shù),作為 “系統(tǒng)時(shí)鐘節(jié)拍”
  一般這個(gè)節(jié)拍是固定的用 OS_TICKS_PER_SEC 這個(gè)標(biāo)志來定義了
  OS_TICKS_PER_SEC = 200 也有的 = 500
  理解大概意思就行,知道有這個(gè)標(biāo)志
  為什么 ???


  下面是 delay_init();
         delay_ms();
   兩個(gè)函數(shù) ,第一個(gè)初始化 系統(tǒng)時(shí)鐘 開啟SYSTICK
   第二就是在有個(gè)別任務(wù)中需要用到的延時(shí)函數(shù)


//初始化延遲函數(shù)
//當(dāng)使用OS的時(shí)候,此函數(shù)會(huì)初始化OS的時(shí)鐘節(jié)拍
//SYSTICK的時(shí)鐘固定為HCLK時(shí)鐘的1/8
//SYSCLK:系統(tǒng)時(shí)鐘



/***********************
要說清楚還需要進(jìn)入這個(gè)延時(shí)函數(shù)初始化中來
這個(gè)函數(shù)最重要的功能是給
fac_ms fac_us賦值
如果是ucos 話進(jìn)入這個(gè)函數(shù)
而且這個(gè)函數(shù)還必須在沒有進(jìn)入中斷中來初始化
void delay_init()
{
#if SYSTEM_SUPPORT_OS                                                          //如果需要支持OS.
        u32 reload;
#endif
                //選擇外部時(shí)鐘  HCLK/8
        SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8);
//這里選擇外部時(shí)鐘原 也就是外部的 8Mhz
//經(jīng)過倍頻后 時(shí)鐘 = 72mhz = 72000 000

        fac_us=SystemCoreClock/8000000;       
//這里計(jì)算 出 延時(shí) 微秒的倍乘數(shù)值
        //為系統(tǒng)時(shí)鐘的1/8  
// fac_us = 72000 000 /8000 000
        //fac_us = 9       
        #if SYSTEM_SUPPORT_OS                                                          //如果需要支持OS.
        //72000000/8000000 = 9
        reload=SystemCoreClock/8000000;                                //每秒鐘的計(jì)數(shù)次數(shù) 單位為K          
        //      = 72000 000 /8000 000
        //  reload = 9;
        //--------------------------------------------
       
        //      = 1000 000 /200
        //      = 1000 0 /2 =5000
        reload*=1000000/delay_ostickspersec;                //根據(jù)delay_ostickspersec設(shè)定溢出時(shí)間
        //reload = reload * 1000 000 /200
        // reload = 9 * 5000
        // reload = 45000     
        // 設(shè)定LOAD 寄存器的最大值
        //就是從45000 開始遞減
       
        //reload為24位寄存器,最大值:16777216,在72M下,約合1.86s左右       
       
        //--------------------------------------------------------
       
        fac_ms=1000/delay_ostickspersec;                        //代表OS可以延時(shí)的最少單位          
  // fac_ms = 1000 /200
  // fac_ms = 5       
        //設(shè)定 延時(shí)毫秒 倍 乘值
       
        //+++++++++++++++++++++++++++++++++++++++++++++++
       
        SysTick->CTRL|=SysTick_CTRL_TICKINT_Msk;           //開啟SYSTICK中斷
        SysTick->LOAD=reload;                                                 //每1/delay_ostickspersec秒中斷一次       
        //這里 LOAD = 45000
       

       
        SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk;           //開啟SYSTICK   
          // 啟動(dòng)嘀嗒定時(shí)器

#else
       
        fac_ms=(u16)fac_us*1000;                                        //非OS下,代表每個(gè)ms需要的systick時(shí)鐘數(shù)   
         // 9*1000 = 9000

#endif
}                                                                    

********************/


我貼過來這個(gè)delay_Init(); 延時(shí)函數(shù)初始化是因?yàn)樵谟行┤蝿?wù)中,
需要用到 delay_ms(); delay_us();
//延時(shí)nus
//nus為要延時(shí)的us數(shù).
//比如                                                                                       
void delay_us(u32 nus)
{               
        int ticks;
        int told,tnow,tcnt=0;
        int reload=SysTick->LOAD;                                        //LOAD的值                     
        // reload = 45000
       
        ticks=nus*fac_us;                                                         //需要的節(jié)拍數(shù)                           
    //這里假設(shè) nus = 10
        //ticks = 10*9
        //這就是需要減 90 次
        //也就是 要從45000減到
        //        44910 就到了延時(shí)時(shí)間
        // 90 = 0x5A;
        // 90 就是 從 45000 減 到 44910

       
        tcnt=0;
        delay_osschedlock();                                                //阻止OS調(diào)度,防止打斷us延時(shí)
        told=SysTick->VAL;                                                //剛進(jìn)入時(shí)的計(jì)數(shù)器值
        // 這是剛進(jìn)入ucos 的最大值
        //
        while(1)
        {
                tnow=SysTick->VAL;       
                //得到現(xiàn)在的的嘀嗒時(shí)鐘的計(jì)數(shù) 值
                //如果現(xiàn)在的值不等于 最初進(jìn)入的計(jì)數(shù)值
                //
               
                if(tnow!=told)   //進(jìn)行比較
                {            
                        //這里注意一下SYSTICK是一個(gè)遞減的計(jì)數(shù)器就可以了.
                        if(tnow<told)   
                                //如果現(xiàn)在的計(jì)數(shù)值 < 剛進(jìn)入的計(jì)數(shù)值
                                  tcnt+=told-tnow;  //微秒延時(shí)使用這個(gè)來計(jì)數(shù)判斷
                          //tcnt = tcnt+told-tnow
                          // 1000 = 1000 +2000-2000
                          // 7998 < 8000
                          // 0 = 0 + 8000 - 7998
                          
                        else
                                tcnt+=reload-tnow+told;          //ms 延時(shí)使用這個(gè)來計(jì)數(shù)
     // tcnt = tcnt +(reload-tnow+told)
     // 0 = 0 + ( 45000 - 1000 +2000 )
     told=tnow;
                        if(tcnt>=ticks)break;                                //時(shí)間超過/等于要延遲的時(shí)間,則退出.
                }  
        };
        //這個(gè) while(); 等待函數(shù)
        //就是經(jīng)過 不停的
        //tnow = tnow -0x14
        //每次循環(huán)一次就減20 個(gè)計(jì)數(shù)
        //直道tcnt = 6D
        //這個(gè)時(shí)候 大于 6D> 5A
        //就直接退出了定時(shí)
        //這里還有個(gè)發(fā)現(xiàn)就是 實(shí)際上定時(shí) us= 10
        //多計(jì)數(shù)了 19 個(gè)計(jì)數(shù)
        delay_osschedunlock();                                                //恢復(fù)OS調(diào)度                                                                            
}
//通過不斷的循環(huán)仿真還是有好處的
//特別對初始化函數(shù) ucos 啟動(dòng)可以很好的理解
//啟動(dòng)是如何運(yùn)行的
//這個(gè)是有些復(fù)雜的啟動(dòng)嘀嗒時(shí)鐘情況
//在有的代碼中只是啟動(dòng)了 systicks 使能了一下
//這里復(fù)雜就是有 延時(shí)函數(shù) 并且是不允許中斷的延時(shí)
//還有就是 延時(shí)是有范圍
//以前可能沒有注意到這些
//在就是 野火的代碼在 啟動(dòng)嘀嗒定時(shí)器的函數(shù)中是有錯(cuò)誤的
//SystICK->CTRL| = 0X07; 在實(shí)際代碼中不是這樣寫的
//但是 他計(jì)算后的情況和上面類似
//這就造成有些位設(shè)置不對
//會(huì)出現(xiàn)設(shè)置過后不能起到作用
//我也是看到有網(wǎng)友碰到了這種情況
//



評分

參與人數(shù) 1黑幣 +20 收起 理由
admin + 20 回帖助人的獎(jiǎng)勵(lì)!

查看全部評分

回復(fù)

使用道具 舉報(bào)

7#
ID:839835 發(fā)表于 2021-3-2 15:22 | 只看該作者
很好的文章
回復(fù)

使用道具 舉報(bào)

8#
ID:7209 發(fā)表于 2021-3-4 20:21 | 只看該作者

謝謝鼓勵(lì)
  delay_ms();
   delay_us();
  delay_Init();
  這三個(gè)函數(shù) 感覺沒有 說明白
  這幾天一直在 想如何在 補(bǔ)充一下
  我的想說的 是
  1  ucos  中的時(shí)鐘節(jié)拍 是如何 算出來的
  2  在任務(wù)中如果要使用 delay_ms(); 是如何使用的 他是如何工作的
      2 -1   還有就是 本來 備案中有 程序一步一步是如何 運(yùn)行的  可 想 不好 最好的表達(dá)方式
  
回復(fù)

使用道具 舉報(bào)

9#
ID:7209 發(fā)表于 2021-3-16 21:22 | 只看該作者
ucos 的任務(wù)想了好幾天
   也寫了些稿子,總覺的都不夠能清楚簡單明了的說明這個(gè)任務(wù)
   任務(wù)在書上說了很多,包括一些視頻分了好幾段來說明
   而我又想不依靠書上了語言來說書上的知識
   這就造成好些“歪理邪說”很有可能誤導(dǎo)一些知識點(diǎn)的解釋
   
還是開始吧
   任務(wù)可以理解 --- 生活中的一項(xiàng)任務(wù)比如燒水
                                    比如洗菜
                   比如 炒菜、比如洗衣服、比如吃飯、比如收拾屋子都是在家庭內(nèi)
                   圍繞特定固定地址 的活動(dòng)
   這些活動(dòng) 可以允許 顛倒 順序
   
   這些活動(dòng) 也可以 根據(jù)需要切換 先后
   
   這些活動(dòng) 也 有 必須立即執(zhí)行的 中斷任務(wù)  
     比如 水開了
     比如 12點(diǎn)了 必須中斷一切別的活動(dòng) 先 吃飯?jiān)谡f
         
   
   這些活動(dòng)也 可以 同步一起做
       比如洗衣機(jī)洗衣服的時(shí)間內(nèi)可以做飯
       洗衣服的時(shí)間內(nèi)可以拖地
       這好像任務(wù)同步了是不是???

   這些活動(dòng)是誰來安排先后順序?
    一般有一個(gè)當(dāng)家的老婆媳婦女朋友來安排
    如果是一個(gè)沒有返回的單身漢就好比一個(gè)
    一家總要有一個(gè)說話算數(shù)的
    一家總要有一個(gè)來協(xié)調(diào)安排先做啥在做啥的
    一家總要有一個(gè) “總管” 的
    void main("有繼承沒有子類的函數(shù)")
     {
      //0
      //1
      //20
      ......
      //110
      ......
     //活夠了                        
     }                                       

    //想想就悲哀
   這些活動(dòng) 還有一些 比如需要燒水 但是現(xiàn)在水瓶內(nèi)還是滿的
                     比如每天需要拖地 但是現(xiàn)在地板還很干凈
                     比如需要做飯 但是你或你和媳婦都不餓
                     這是不是就相當(dāng)于 有需求 但是先掛了起來不執(zhí)行

  先說 一家的 “ 總管” 吧!
  她   --- 是如何管理你和你的家的
  她   --- 是如何給你分配干活的工具的
  她   --- 是如何給你分配先干啥后干啥的
  她   --- 是如何給你劃的道道的

  在實(shí)際應(yīng)用程序設(shè)計(jì)中,通常需要把握完成的工作分成多個(gè)任務(wù)
  每個(gè)任務(wù)只負(fù)責(zé)一項(xiàng)工作
  一個(gè)任務(wù)是一個(gè) “線程”(計(jì)算機(jī)離不開叫線程的)
  實(shí)際上早期只有一個(gè)CPU
  某刻只能做一個(gè)任務(wù)
  ucos 支持多任務(wù)管理
  允許有無數(shù)個(gè)任務(wù)
  但是一般受限CPu 和存儲器的容量
  
  多任務(wù)其實(shí)就是多個(gè)任務(wù)間的切換和調(diào)度
  在任務(wù)相繼執(zhí)行過程中
  CPU 的使用權(quán)在任務(wù)間切換
  
  創(chuàng)建后的任務(wù)函數(shù)是這樣的
  
  void Task_task1(void* p_arg)
  這里我想說的是
  void *p_arg
  這和在普通函數(shù)的形參一樣
  這個(gè)參數(shù)是 void 型指針
  該指針是一個(gè)通用的指針變量
  可以向任務(wù)傳遞一個(gè) “變量地址”
  傳遞一個(gè)結(jié)構(gòu)體
  甚至 傳遞一個(gè)函數(shù)入口地址


   生活中我們處理一個(gè)大問題的時(shí)候通常都是將這個(gè)問題“分而治之”,
   把大問題分成多個(gè)小問題,
   小問題被逐步的解決掉,
   大問題也就隨之解決了。
   那么這些小問題就可以看成是很多個(gè)小任務(wù)。
   
   在我們設(shè)計(jì)復(fù)雜、大型程序的時(shí)候也是一樣的,
   將這些負(fù)責(zé)的程序分割成許多個(gè)簡單的小程序,
   這些小程序就是單個(gè)的任務(wù),
   所有的小任務(wù)融洽的工作,
   最終完成復(fù)雜的功能。
   在操作系統(tǒng)中這些小任務(wù)可以并發(fā)執(zhí)行,
   從而提高CPU的使用效率。
   
   UCOSIII就是一個(gè)可剝奪的多任務(wù)系統(tǒng),
   我們使用UCOSIII的一個(gè)重要 的原因就是它的多任務(wù)處理能力。  

(
任務(wù)說白了就是一個(gè)大的工作分若干個(gè)人來共同完成
每個(gè)人就相當(dāng)于與一個(gè)獨(dú)立的任務(wù)
最后在系統(tǒng)的協(xié)調(diào)下
共同完成這項(xiàng)工作
)

評分

參與人數(shù) 1黑幣 +20 收起 理由
admin + 20 共享資料的黑幣獎(jiǎng)勵(lì)!

查看全部評分

回復(fù)

使用道具 舉報(bào)

10#
ID:86450 發(fā)表于 2021-3-17 08:40 | 只看該作者
這么好的文章 。。
回復(fù)

使用道具 舉報(bào)

11#
ID:7209 發(fā)表于 2021-3-18 20:15 | 只看該作者
/***********************************************
感謝版主不辭辛苦的給予的“黑幣”獎(jiǎng)金鼓勵(lì)
感謝各位老師給予的夸獎(jiǎng)評價(jià)
在學(xué)習(xí)的路上不敢驕傲
在項(xiàng)目的路上老板
表揚(yáng)的好似只有 0 回和 1回
更多的是

來 小X 這個(gè)需求在改改
   小X 這個(gè)功能能不能在添加一個(gè)新的創(chuàng)意
   小X 這個(gè)邏輯有些菜
   小X 這個(gè)項(xiàng)目進(jìn)展有些慢
   小X 這個(gè)設(shè)備怎么設(shè)計(jì)的有bug
   ...........
   ...........
   第一年我羨慕大佬
   第二年我羨慕老板
   第三年我羨慕搬磚
   第四年 ......搬磚
  ........     搬磚
  ........搬磚
  ........ 搬磚
  .........搬磚
  (還想寫,但是咱是來學(xué)習(xí)的)

后來想想就是個(gè)菜鳥
適合搬磚
其實(shí)想想
無論多么牛逼
都是個(gè)打工的
在別人眼里都是個(gè)工具

除非達(dá)到前幾年
航天行業(yè)的那個(gè)兄弟
自己走了
那幫人玩不轉(zhuǎn)
************************************/
//一直想從整體上說任務(wù)
//分開了說
//老忘記前面學(xué)的啥 (比較笨)
  
   任務(wù)是以何種面貌存在的呢?
   在UCOSIII中任務(wù)就是程序?qū)嶓w,
   每個(gè)任務(wù)就是一個(gè) void main(); 函數(shù)
   UCOSIII能夠管理和調(diào)度這些小任務(wù)(程序)。
   任務(wù)的設(shè)計(jì)也是整個(gè)軟件代碼的基礎(chǔ)
   其他設(shè)計(jì)工作都是圍繞一個(gè)個(gè)小任務(wù)來展開的
   
   在不看書本的知識情況下想一想
   做飯吃飯這類任務(wù)
   是不是 ----是個(gè)重復(fù)的或說周期類執(zhí)行的任務(wù)
   
下館子這類任務(wù)
是不是 ----是個(gè)事件觸發(fā)類事物
   {
    //女朋友生日、老婆生日、朋友想你了陪他喝會(huì)兒
    //都是在受到外部刺激了
    //或受到外部觸發(fā)了
    //才產(chǎn)生一次)  
   }



老婆給你買衣服這類任務(wù)
   是不是 ----是不是個(gè)單次執(zhí)行類任務(wù)
   {
     //小姑娘可以一月買兩件或三件衣服
     //大老爺們你一月買三件試試
     //大部分是一對鞋破了直接扔掉買對新的
     //衣服爛了小了在買一套替換
    }  

   
周期類或重復(fù)任務(wù)---- 比如做飯
   {
   準(zhǔn)備好菜
   洗好米
   和好面
   --------這都是準(zhǔn)備的 狀態(tài)
   炒菜、蒸米、下面
   ------- 這是執(zhí)行的狀態(tài)
   蒸米需要10分鐘
   炒菜需要5分鐘
   面熟需要8分鐘
   --------這是等待狀態(tài)
   
  (這里一定別小看 等待的 狀態(tài)這個(gè)狀態(tài)忒有必要了)
   /***
   為什么這里等待很有必要
   其實(shí)等待的時(shí)間就是讓CPU來
   切換不同的任務(wù)
   否則 一個(gè)任務(wù)寫個(gè) while(1) {   ......}
   一直運(yùn)行不出來?
   咋運(yùn)行別的任務(wù)
   這里也是系統(tǒng)的最好的地方
   系統(tǒng)內(nèi)怎么切換的
   暫時(shí)不管它
   ****/
   }   
   
//下面繼續(xù)偽代碼
  
/**單次執(zhí)行類任務(wù)-----就是女朋友給你買衣服******/
  
   鞋破了衣服爛了
   給當(dāng)家的匯報(bào)---------這是創(chuàng)建任務(wù)

   通過了同意了
   給錢了,并且買到了----這是運(yùn)行了任務(wù)
   {
    這也有可能
    給錢了同意了
    但是現(xiàn)在不同意去購買去執(zhí)行
   }
   
   買到了試試合適
   還想要一個(gè)“機(jī)械鍵盤”的可愛要求
        ---- 直接刪除這個(gè)任務(wù)3
  

   void my_Task_clothing(void *pdata)
   {
    //進(jìn)行準(zhǔn)備工作 定義和初始化變量
    //任務(wù)實(shí)體 完成衣服具體購買
    //任務(wù)刪除 將這月買衣服的任務(wù)刪除
   
    }   


/***周期類任務(wù) 做飯吃飯************************/   


   void my_Task_have_a_meal(void *pdata)
   {
    //進(jìn)行準(zhǔn)備工作
    //食材
    while(1)
     {
      //做飯
      //吃飯
      //等待延時(shí) 沒到飯點(diǎn),沒有餓的需求。
      }
   }

/***觸發(fā)類任務(wù) 有約去外吃飯**********************/

  void my_Task_eat(void *pdata)
  {
    //進(jìn)行準(zhǔn)備工作
    //準(zhǔn)備穿的衣服
    //準(zhǔn)備好酒
    //化妝
   while(1)
    {
      //等待朋友發(fā)的位置
      //或給朋友發(fā)吃飯的位置
      //也就是獲取別人的請求
      //接受到消息后
      //開始一起吃飯
      //聊天
      //等待下一次彼此聚餐
    }
   }



評分

參與人數(shù) 1黑幣 +20 收起 理由
admin + 20 回帖助人的獎(jiǎng)勵(lì)!

查看全部評分

回復(fù)

使用道具 舉報(bào)

12#
ID:7209 發(fā)表于 2021-3-19 17:48 | 只看該作者
繼續(xù)說說和書上沒有關(guān)系的白話
  這么多任務(wù)
  有是單任務(wù)、
  有是觸發(fā)類任務(wù)、
  又是周期類或重復(fù)類任務(wù)
  
  又是出外吃飯、又是買衣服、又是在家做飯吃飯
  
  這些任務(wù)應(yīng)該怎么安排?
  安排不好就是-----生活的雞飛狗跳
  這就出現(xiàn)一個(gè)問題----先后順序
  那個(gè)任務(wù)應(yīng)該安排在最靠前?
  那個(gè)任務(wù)可以安排的次一些?
  那個(gè)任務(wù)可以安排的靠后一些?
  哪些任務(wù)可以協(xié)調(diào)為有需求在執(zhí)行的觸發(fā)性任務(wù)?
  哪些任務(wù)可以安排為臨時(shí)性或突發(fā)性任務(wù)?
  
  如何安排先后順序--- 優(yōu)先級 ----???
  無論幾個(gè)任務(wù)這個(gè)中心非常重要
  如果不能安排好就會(huì)造成系統(tǒng)不能協(xié)調(diào)工作
  
  1---首先要滿足這個(gè)項(xiàng)目對"實(shí)時(shí)性"的要求,這也是ucos吹的地方。
  2---在就是多少個(gè)任務(wù)系統(tǒng)協(xié)調(diào)起來最合適,想想是不是任務(wù)
      數(shù)目越少越好,要是就兩個(gè)或三個(gè)四個(gè)任務(wù)
      系統(tǒng)跑起來都不是事
  3---在就是適當(dāng)簡化或屏蔽掉一些系統(tǒng)的多余的用不到的功能   
      這個(gè)暫時(shí)理解即可,知道在ucos中可以屏蔽一些功能
  4---任務(wù)和中斷、任務(wù)和任務(wù)、重復(fù)類和單次任務(wù)之間
      聯(lián)系適當(dāng)或合理簡化數(shù)據(jù)的同步和通信需求
      從而降低或減少對系統(tǒng)資源的時(shí)間上的影響
  當(dāng)然,合適不合適跑跑就知道了
  實(shí)踐--- 實(shí)踐 ----- 實(shí)踐
  

  缺一不可類任務(wù)或關(guān)鍵類任務(wù)
             任務(wù)優(yōu)先級安排越高越好,必須保障其執(zhí)行機(jī)會(huì)

  周期性頻繁類任務(wù)
             任務(wù)優(yōu)先級安排也要高,一般這類任務(wù)都執(zhí)行時(shí)間都不會(huì)長
                 在寫的時(shí)也要保證這類任務(wù)盡量簡短

  快速響應(yīng)類實(shí)際環(huán)境中的傳感器更新數(shù)據(jù)類任務(wù)
             任務(wù)優(yōu)先級安排也要高,以確保數(shù)據(jù)的實(shí)時(shí)性

  ---交換性或上下任務(wù)通信數(shù)據(jù)傳遞、信號數(shù)據(jù)處理類
             任務(wù)優(yōu)先級安排低于快速響應(yīng)類
  
  致命性危險(xiǎn)性緊迫性破壞性非常嚴(yán)重性任務(wù)
             任務(wù)一般采用與中斷有聯(lián)系
  
  這么多都要求優(yōu)先級高
  確實(shí)不好處理
  舉一個(gè)例子吧
  
   中國保護(hù)動(dòng)物共分為三個(gè)級別。

   一級保護(hù)動(dòng)物:金絲猴、雪豹、中華白海豚、西藏野驢、梅花鹿、野牦牛藏羚羊等。

   二級保護(hù)動(dòng)物:短尾猴、獼猴、藏酋猴、穿山甲、豺、黑熊、棕熊、石貂、水獺等。

   三級保護(hù)動(dòng)物:黃鼬、青鼬、中華竹鼠、銀星竹鼠等。

   這雖然不是一個(gè)行業(yè)的
   但是動(dòng)物保護(hù)分級能很好說明就是這樣的一個(gè)意思
   在國家保護(hù)動(dòng)物中分1、2、3的優(yōu)先性
   這也是在任務(wù)分配中各個(gè)任務(wù)的優(yōu)先級   
     
前面蒸米煮面條需要等待為什么很有必要???
   答: 這是因?yàn)閡cos 是完全基于優(yōu)先級的操作系統(tǒng)
        所以一定條件下必須出讓cpu占有權(quán)以便比自己優(yōu)先級更低的任務(wù)
        能夠運(yùn)行
        這是通過調(diào)用部分系統(tǒng)函數(shù)來實(shí)現(xiàn)的
        這些函數(shù)如下表---
        一般的任務(wù)必須調(diào)用至少一個(gè)表里的函數(shù)
        只有一種情況除外
        就是單次執(zhí)行的任務(wù)
        因?yàn)槿蝿?wù)刪除后肯定出讓CPU
        所以可以不調(diào)用表中的函數(shù)
  
  (看看就行不用記住)
  OSFlagPend   --- 等待事件標(biāo)志組的事件標(biāo)志位
               (類似手機(jī)里APP的屏幕通知)
  OSQPend      --- 等待消息隊(duì)列中的消息
               (類似 QQ 中別人給你打字你看到別人正在輸入)
  OSSemPend    --- 等待一個(gè)信號量
               (類似摩斯密碼
                 等待前線發(fā)送過來,
                 指揮所根據(jù)發(fā)送的字符
                 了解前線情況
                 還有些信號量有廣播的功能)
  OSTimeDly    --- 延時(shí)
  OSMutexPend  --- 等待一個(gè)互斥信號量
                (類似對講機(jī) 每次只能一個(gè)人說話另外一個(gè)人聽)
  這些只是生活中的比喻,有些不恰當(dāng)
  
  OSQPend      --- 等待消息隊(duì)列中的消息
  OSTaskSuspend -- 掛起任務(wù)
  OSTimeDlyHMSM -- 延時(shí)

  上面這幾個(gè)函數(shù)都能引起任務(wù)函數(shù)的時(shí)間等待

   任務(wù)由三部分組成:
   任務(wù)堆棧、任務(wù)控制塊、任務(wù)函數(shù)。

任務(wù)由這三部分組成都是啥意思啊?
  答:任務(wù)堆棧 --- 理解為倉庫
      任務(wù)控制塊 - 理解為倉庫管理員
      任務(wù)函數(shù) --- 理解為物流司機(jī)
      現(xiàn)在網(wǎng)絡(luò)購物方便實(shí)惠
      我們下單子后是給商家---這就是發(fā)送了一個(gè)請求信號量 (這里注意了)
      
      商家接收到下的單子也就是信號量開始對單子處理
      或?qū)δ阗徺I的東西進(jìn)行確認(rèn)
      (商家需要和賣家知道彼此說的是啥)
     
      開始備貨  (這是不是就是創(chuàng)建了一個(gè)任務(wù))
      
      開始對任務(wù)進(jìn)行具體操作
      貨物現(xiàn)在需要在倉庫里有個(gè)存儲空間 (這就是任務(wù)堆棧了)
      貨物在倉庫中有進(jìn)出關(guān)系
      ucos 系統(tǒng)在處理任務(wù)堆棧也有進(jìn)出關(guān)系
      (這個(gè)和實(shí)際ucos 中一樣也有先進(jìn)先出或后進(jìn)先出規(guī)則)
      別管是啥進(jìn)出規(guī)則

      這個(gè)堆棧里或倉庫里保存了這件商品的基本信息
      
      倉庫管理員來管理這個(gè)商品是發(fā)給誰 (這就是任務(wù)控制塊)
      倉庫管理員好牛啊
      控制管理層大小是個(gè)領(lǐng)導(dǎo)
      
      庫管決定后通知任務(wù)函數(shù)
      任務(wù)函數(shù)來規(guī)劃是發(fā)到北京還是宇宙
      是走路地還是航空
      (這就是憑本事吃飯了自己發(fā)揮了只要能完成給客戶的商品發(fā)送)
      任務(wù)其實(shí)就是個(gè)干具體工作的
      完成具體任務(wù)
      是個(gè)苦逼的打工仔
   

評分

參與人數(shù) 1黑幣 +20 收起 理由
admin + 20 回帖助人的獎(jiǎng)勵(lì)!

查看全部評分

回復(fù)

使用道具 舉報(bào)

13#
ID:7209 發(fā)表于 2021-3-21 22:07 | 只看該作者
下面這幾句話也是在網(wǎng)絡(luò)上看到,感覺寫的很通俗易懂供參考:

  任務(wù)狀態(tài)
簡單分為運(yùn)行態(tài),就緒態(tài),阻塞態(tài)。


運(yùn)行態(tài):萬事俱備,不欠東風(fēng)(獲得CPU控制權(quán));

就緒態(tài):萬事俱備,只欠東風(fēng)(缺少CPU控制權(quán));

阻塞態(tài):萬事不俱備(等事件或信號),還欠東風(fēng)(缺少CPU控制權(quán));

  (運(yùn)行態(tài):老板簽過字、銀行正常上班有錢------可以正常發(fā)薪水)
  (就緒態(tài):老板沒簽字、銀行正常上班有錢 ----- 還需要等待)
  (阻塞態(tài):老板沒簽字、銀行正常上班沒錢 ----- 還需要等待)



每個(gè)任務(wù)基本上都會(huì)游離于這三種狀態(tài)。

運(yùn)行到阻塞,就緒到運(yùn)行稱為任務(wù)切換過程。


從用戶的角度看,UCOSIII的任務(wù)一共有5種狀態(tài):
    1、休眠態(tài):
       任務(wù)已經(jīng)在CPU的flash中了,
       但是還不受UCOSIII管理。

    2、就緒態(tài):
       系統(tǒng)為任務(wù)分配了任務(wù)控制塊,
       并且任務(wù)已經(jīng)在就緒表中登記,
       這時(shí)這個(gè)任務(wù)就具有了運(yùn)行的條件,
       但是沒有獲得CPU 的使用權(quán)
       此時(shí)任務(wù)的狀態(tài)就是就緒態(tài)。

    3、運(yùn)行態(tài):
       任務(wù)獲得CPU的使用權(quán),正在運(yùn)行。

    4、等待態(tài):
       正在運(yùn)行的任務(wù)需要等待一段時(shí)間,
       或者等待某個(gè)事件,
       這個(gè)任務(wù)就進(jìn)入了等待態(tài),
       此時(shí)系統(tǒng)就會(huì)把CPU使用權(quán)轉(zhuǎn)交給別的任務(wù)。


    5、中斷服務(wù)態(tài):
       當(dāng)發(fā)送中斷,
       當(dāng)前正在運(yùn)行的任務(wù)會(huì)被掛起,
       CPU轉(zhuǎn)而去執(zhí)行中斷服務(wù)函數(shù),此時(shí)任務(wù)的任務(wù)狀態(tài)叫做中斷服務(wù)態(tài)。


白話任務(wù)堆棧、任務(wù)控制塊、任務(wù)函數(shù)



  在多任務(wù)操作系統(tǒng)中創(chuàng)建任務(wù)時(shí),都需要指定該任務(wù)的堆棧大小,
  那么這個(gè)堆棧的作用時(shí)什么呢?
  什么情況下需要用到堆棧,以及大小不夠時(shí)會(huì)產(chǎn)生什么異常呢?



任務(wù)堆棧的作用:


1 任務(wù)處于運(yùn)行狀態(tài):
當(dāng)任務(wù)在運(yùn)行時(shí),
   一般都會(huì)調(diào)用各式各樣的函數(shù),
   而函數(shù)的局部變量,參數(shù),返回值是存在于函數(shù)棧幀里的,
   每個(gè)函數(shù)都擁有獨(dú)立的棧幀,
   各個(gè)棧幀使用的空間就是任務(wù)堆棧的空間。
   所以任務(wù)堆棧的作用是用于保存函數(shù)在運(yùn)行/調(diào)用過程中的參數(shù)/局部變量。

   (理解堆棧就是個(gè)倉庫倉庫里各種各樣的商品也就是各種功能不同函數(shù))




2 任務(wù)處于切換
當(dāng)運(yùn)行的任務(wù)被切換時(shí),需要保護(hù)現(xiàn)場(CPU中寄存器的值),
   以便于下次恢復(fù)數(shù)據(jù)。
   所以任務(wù)堆棧的作用是用于保存CPU中寄存器的值。

3

任務(wù)(低優(yōu)先級的)在運(yùn)行過程中,
   隨時(shí)可能被切換,
   所以CPU中寄存器的值入棧的棧位置是不確定的,
   這取決于當(dāng)前任務(wù)的執(zhí)行情況。



4 堆棧溢出
若堆棧的空間設(shè)置太大,會(huì)浪費(fèi)內(nèi)存資源。
   而設(shè)置得太小,則會(huì)出現(xiàn)堆棧溢出,在沒有MMU功能的操作系統(tǒng)中,
   可能會(huì)導(dǎo)致系統(tǒng)奔潰。
所以,
   需要根據(jù)任務(wù)的情況設(shè)置合適的堆棧大小。
   同時(shí),應(yīng)避免使用遞歸調(diào)用函數(shù),
   函數(shù)中局部變量的分配空間不能太大。


   任務(wù)堆棧是任務(wù)的重要部分,
   堆棧是在RAM中按照“先進(jìn)先出(FIFO)”的原則   
   組織的一塊連續(xù)的存儲空間。

   為了滿足任務(wù)切換和響應(yīng)中斷時(shí)保存CPU寄存器中的內(nèi)容及
   任務(wù)調(diào)用其它函數(shù)時(shí)的需要,
   每個(gè)任務(wù)都應(yīng)該有自己的堆棧。

   一般是這樣定義的
   #define START_STK_SIZE  512        //堆棧大小
   CPU_STK START_TASK_STK[START_STK_SIZE];//定義一個(gè)數(shù)組來作為任務(wù)堆棧

   一般就是這樣定義的,
   明白就行不能有壓力。

  任務(wù)堆棧的大小是多少呢?

  CPU_STK為 CPU_INT32U類型,
  也就是  unsigned int類型,
  為4字節(jié)的,
  那么任務(wù)堆棧
  START_TASK_STK的大小就為:512 X 4=2048字節(jié)!




  任務(wù)如何才能切換回上一個(gè)任務(wù)
  并且還能接著從上次被中斷的地方開始運(yùn)行?

  這一點(diǎn)很重要系統(tǒng)是如何來切換任務(wù)的?
  它是怎么知道某一個(gè)任務(wù)運(yùn)行到了那里?
  它是怎么來記錄任務(wù)運(yùn)行過程中產(chǎn)生的數(shù)據(jù)?

    這就是任務(wù)堆棧初始化的工作
    這里是不是和剛學(xué)習(xí)單片機(jī)c51有些類似

    org 0x0300
    ljmp main
main: mov r0,r1
     .....
     .....
     .....
     .....
     ajmp main

     道理是一樣的
     只不過在C 中我們直接定義了幾個(gè)大的ROM
     每個(gè)ROM有是連續(xù)的存儲空間
     好似這樣的結(jié)構(gòu)



     ................
     .   c51        .     
     .              .     
     .              .     
     .  void main() .     
     .              .     
     .              .         
     .              .     
     ................

     ........................................................
     .   stm32      .                                       .
     .        ucos - iii       .                            .
     ........................................................     
     .  void main() .            .            .             .
     .              .void main() .            .             .
     .              .            .void main() .             .
     .              .            .            . void main() .
     ........................................................   


     51 的ROM 空間有過2K 、16K、64K 的
     STM32 的空間就大的多了
     這樣利用ucos iii 的組織能力就能在其內(nèi)部分割出來
     相同或不相同的 void main(); 來
     這其實(shí)就是任務(wù)堆棧的原型了。
     至于在單片機(jī)內(nèi)部是如何分配的就不知道了。




    知道堆棧的大概了那么
    恢復(fù)現(xiàn)場就是重新讀取保存下來的CPU的內(nèi)部各個(gè)寄存器數(shù)據(jù)。


    因此在創(chuàng)建一個(gè)新任務(wù)時(shí),
    必須把系統(tǒng)啟動(dòng)這個(gè)任務(wù)時(shí)所需的CPU各個(gè)寄存器初始值事先存放在任務(wù)堆棧中。

    這樣當(dāng)任務(wù)獲得CPU使用權(quán)時(shí),

    就把任務(wù)堆棧的內(nèi)容復(fù)制到CPU的各個(gè)寄存器,
    從而可以任務(wù)順利地啟動(dòng)并運(yùn)行。


    把任務(wù)初始數(shù)據(jù)存放到任務(wù)堆棧的工作就叫做任務(wù)堆棧的初始化,
    UCOSIII  提供了完成堆棧初始化的函數(shù):
    OSTaskStkInit()。

    CPU_STK  *OSTaskStkInit (OS_TASK_PTR    p_task,
                             void          *p_arg,
                             CPU_STK       *p_stk_base,
                             CPU_STK       *p_stk_limit,
                             CPU_STK_SIZE   stk_size,
                             OS_OPT         opt)


   用戶一般不會(huì)直接操作堆棧初始化函數(shù),
   任務(wù)堆棧初始化函數(shù)由任務(wù)創(chuàng)建函數(shù)OSTaskCreate()調(diào)用。
   不同的CPU對于的寄存器和對堆棧的操作方式不同,
   因此在移植UCOSIII的時(shí)候需要              
   用戶根據(jù)各自所選的CPU來編寫任務(wù)堆棧初始化函數(shù)。



前面我們創(chuàng)建了一個(gè)任務(wù)堆棧,怎么使用這個(gè)任務(wù)堆棧?

作為任務(wù)創(chuàng)建函數(shù)OSTaskCreate()的參數(shù),
               函數(shù)OSTaskCreate()如下:

void  OSTaskCreate (OS_TCB        *p_tcb,
                    CPU_CHAR      *p_name,
                    OS_TASK_PTR    p_task,
                    void          *p_arg,
                    OS_PRIO        prio,
                    CPU_STK       *p_stk_base,         //任務(wù)堆;刂
                    CPU_STK_SIZE   stk_limit,        //任務(wù)堆棧棧深
                    CPU_STK_SIZE   stk_size,        //任務(wù)堆棧大小
                    OS_MSG_QTY     q_size,
                    OS_TICK        time_quanta,
                    void          *p_ext,
                    OS_OPT         opt,
                    OS_ERR        *p_err)

    其實(shí)看著有些復(fù)雜,其實(shí)很多參數(shù)都是一定的;
    學(xué)習(xí)過后就理解
    基礎(chǔ)東西很重要
    特別是C 語言的基礎(chǔ)知識和算法
    因?yàn)榛A(chǔ)的都是實(shí)際來處理具體問題的
    即便上了系統(tǒng)
    系統(tǒng)也只是起到一個(gè)調(diào)度的作用
    平衡各個(gè)任務(wù)之間的運(yùn)行

函數(shù)OSTaskCreate()中的參數(shù)p_stk_base如何確定?

   根據(jù)堆棧的增長方式,
   堆棧有兩種增長方式:
   向上增長:堆棧的增長方向從低地址向高地址增長。
   向下增長:堆棧的增長方向從高地址向低地址增長

   函數(shù)OSTaskCreate()中的參數(shù)p_stk_base是任務(wù)堆棧基地址,
   那么如果CPU的堆棧是向上增長的話
   那么基地址就&START_TASK_STK[0],
   如果CPU堆棧是向下增長的話
   基地址就是&START_TASK_STK[START_STK_SIZE-1]
   STM32的堆棧是向下增長的!

  寫了很多廢話,只是 為了了解任務(wù)堆棧
  也寫的沒有趣味性了
  失敗




評分

參與人數(shù) 1黑幣 +20 收起 理由
admin + 20 回帖助人的獎(jiǎng)勵(lì)!

查看全部評分

回復(fù)

使用道具 舉報(bào)

14#
ID:7209 發(fā)表于 2021-3-24 13:35 | 只看該作者
任務(wù)堆棧: 就是上下文切換的時(shí)候用來保存任務(wù)的工作環(huán)境,
           若是使用STM32的話用來保存內(nèi)部寄存器值,
           無論是中斷還是任務(wù)切換都要產(chǎn)生需要保存的
           能維持任務(wù)中斷或任務(wù)切換過后的正常運(yùn)行的數(shù)據(jù)。
   

2 任務(wù)控制塊
是任務(wù)的抽象類型,用于描述其屬性和方法

     任務(wù)控制塊好似讓做飯這項(xiàng)任務(wù)的基礎(chǔ)包
     做啥飯
     都有啥蔬菜
     油鹽醬醋
     包括盛菜的盤子
     這就是任務(wù)的基礎(chǔ)包
     里面有完成任務(wù)的必要材料
     以及去倉庫拿這些食材
     廚師好似任務(wù)控制塊,控制做出的飯菜味道營養(yǎng)
     (那么做出的菜就好比任務(wù)函數(shù),送到不同的餐桌,起不同的功能)
   
     用來記錄任務(wù)的堆棧指針、任務(wù)的當(dāng)前狀態(tài)、任務(wù)的優(yōu)先級別
     等一些與任務(wù)管理有關(guān)的屬性的表稱為任務(wù)控制塊
   
     用來記錄倉庫里商品的存放位置、倉庫有多少商品、商品的價(jià)格
     等一些商品的屬性就是任務(wù)控制塊也就是 庫管。
     而且在倉庫里任務(wù)控制塊制作一個(gè)excel表就是一個(gè)表格
     
     一般倉庫都是一格一格這樣擺放的
     也就是說只要使用這個(gè)倉庫
     這樣的空格子就是連續(xù)的
     對應(yīng)ucos就是一條空任務(wù)鏈表
     既然有空的肯定有實(shí)的任務(wù)列表
     實(shí)的就是我們實(shí)際創(chuàng)建任務(wù)產(chǎn)生的任務(wù)控制塊
     也就是在倉庫里擺放了 100件
     實(shí)際存在的商品
     (在ucos III中規(guī)定了47個(gè)這樣的參數(shù)來說明內(nèi)部的消息)
   
  
      
     任務(wù)控制塊是用來記錄與任務(wù)相關(guān)的信息的數(shù)據(jù)結(jié)構(gòu),
     每個(gè)任務(wù)都要有自己的任務(wù)控制塊。     
     任務(wù)控制塊由用戶自行創(chuàng)建,
     如下代碼為創(chuàng)建一個(gè)任務(wù)控制塊:
   
     
     
     OS_TCB StartTaskTCB;  //創(chuàng)建一個(gè)任務(wù)控制塊

     OS_TCB為一個(gè)結(jié)構(gòu)體,
     描述了任務(wù)控制塊,
     任務(wù)控制塊中的成員變量用戶不能直接訪問,
     更不可能改變他們。

     OS_TCB為一個(gè)結(jié)構(gòu)體,其中有些成員采用了條件編譯的方式來確定


     任務(wù)控制塊初始化函數(shù):
     OSTCBInit()
      
     下面是ucos ii中的任務(wù)控制塊初始化函數(shù)
     INT8U OSTCBInit(
       INT8U prio,   //任務(wù)的優(yōu)先級別
       OS_STK  *ptos,  //任務(wù)堆棧棧頂指針
       OS_STK  *pbos,  //任務(wù)堆棧低指針
       INT16U id,      //任務(wù)的標(biāo)識符
       INT16U stk_size, //任務(wù)堆棧的長度
       void *pext,     //任務(wù)控制塊的擴(kuò)展指針
       INT16U opt);    //任務(wù)控制塊的選擇項(xiàng)
    (這里III 對任務(wù)控制塊參數(shù)達(dá)到47個(gè)忒復(fù)雜了怕一下嚇懵了,
     知道大概有哪些東西就行)
    INT8U OSTCBInit(
         //商品的價(jià)格
         //商品的最多的數(shù)目
         //商品最少的數(shù)目
         //商品的標(biāo)志
         //倉庫對該商品分配的存儲空間大小
         //該商品如果在規(guī)定存儲空間放不下如何在新空間來標(biāo)志
         //商品的其他選擇項(xiàng)目
         );
    該函數(shù)啥作用?
      -- 對創(chuàng)建該商品放入整個(gè)倉庫的商品目錄中
      -- 為商品進(jìn)行說明
      -- 為該商品在倉庫存放(堆棧內(nèi))指定位置


   
   II 和 III 任務(wù)控制塊里所包含的參數(shù)不一樣
   III 的參數(shù)多多了
回復(fù)

使用道具 舉報(bào)

15#
ID:901261 發(fā)表于 2021-4-6 12:50 | 只看該作者
謝謝樓主的發(fā)帖,我正在學(xué)習(xí)ucosII  ,感覺你讓我受到了很大的啟發(fā)
回復(fù)

使用道具 舉報(bào)

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規(guī)則

手機(jī)版|小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術(shù)交流QQ群281945664

Powered by 單片機(jī)教程網(wǎng)

快速回復(fù) 返回頂部 返回列表