• <li id="00i08"><input id="00i08"></input></li>
  • <sup id="00i08"><tbody id="00i08"></tbody></sup>
    <abbr id="00i08"></abbr>
  • 新聞中心

    EEPW首頁 > 嵌入式系統 > 設計應用 > 關于ucos中os_tmr.c中的代碼分析

    關于ucos中os_tmr.c中的代碼分析

    作者: 時間:2016-11-24 來源:網絡 收藏
    我本身也是個初學者,喜歡嵌入式而自學ucos系統,ucos是個開源的代碼,短小而又簡單,這是我學習的筆記,希望能對喜歡ucos的人有一點幫助,因本人也是初學者,如有錯誤迎指點。一般的書多是2.5版本,沒有os_tmr.c,所以我寫了關于這部分代碼的分析。
    我讀ucos.中的os_tmr.c:
    我想這個文件里就是為了寫一個建立在操作系統的定時器,原來我們學的時鐘節拍就像cpu總線時鐘脈沖一樣。我們建立的是定時器結構體,在os_tmr.c中有一個函數OSTmr_Task()這個函數對定時器結構體的信息進行處理,在定時時間到了時候,該定時器中的一個指向回調函數的指針就調用這個回調節器函數進行工作,當然,你要寫回調函數,不然就什么也不做,以前做過ucos移植的人知道要寫一個硬件定時器中斷函數,這回要加個OSTmrSignal()這里有個發送信號。我們學硬件時知道,用到硬件定時器時要給它一個計算脈沖。這個軟件定時器也要一個計算脈沖。我們建立的定時器結構體都會掛到OSTmrWheelTbl[OS_TMR_CFG_WHEEL_SIZE]上面,OS_TMR_CFG_WHEEL+SIZE是要自己定義的,至于掛到OSTmrWheelTbl[0] 到OSTmrWheelTbl[OS_TMR_CFG_WHEEL_SIZE-1]哪一個上,只要看一下OSTmr_Link (OS_TMR *ptmr, INT8U type)就明白了,而且一個OSTmrWheelTbl[n]上可以掛很多個定時器結構體。
    一、定時器的建立:
    定時器是在我們的應用程序中建立的,
    OS_TMR *OSTmrCreate (INT32U dly,
    INT32U period,
    INT8U opt,
    OS_TMR_CALLBACK callback,
    void *callback_arg,
    INT8U *pname,
    INT8U *perr)
    想使用定時器那些函數要在os_cfg.h中定義 OS_TMR_EN。
    返回值是os_tmr結構體(定義在ucos_ii.h中)。
    typedef struct os_tmr {
    INT8U OSTmrType;
    OS_TMR_CALLBACK OSTmrCallback;
    void *OSTmrCallbackArg;
    void *OSTmrNext;
    void *OSTmrPrev;
    INT32U OSTmrMatch; 當 OSTmrTime == OSTmrMatch 定時器到時間了。
    INT32U OSTmrDly;
    INT32U OSTmrPeriod;
    #if OS_TMR_CFG_NAME_EN > 0u
    INT8U *OSTmrName;
    #endif
    INT8U OSTmrOpt;
    INT8U OSTmrState;


    } OS_TMR;
    OSTmrType類型定義在ucos_ii.h中:OS_TMR_TYPE
    OS_ARG_CHK_EN要在os_cfg.h中定義一下,來確定要不要一些功能。
    OS_TMR_CFG_NAME_EN要你自己在os_cfg.h中定義,來控制要不要用OSTmrName
    OSTmrState在ucos_ii.h中有以下幾種類型:
    OS_TMR_STATE_UNUSED 不存在這個定時器
    OS_TMR_STATE_RUNNING 這個定時器正在運行
    OS_TMR_STATE_COMPLETED這個定時器已經跑完了
    OS_TMR_STATE_STOPPED 這個定時器停止了
    參數:
    1. Dly 定時時間,如果是這個定時器只用一次,那么就用這個,如果定時器要反復用那么它是第一次時用,以后用period。
    2. Period 定時器從復用時會用到這個作定時時間。
    3. Opt 這里有兩種選項,告訴我們是只用一次還是反復使用。只用一次OS_TMR_OPT_ONE_SHOT,反復使用OS_TMR_OPT_PERIODIC。這些定義在ucos_ii.h中。
    定時器選項有五種
    #define OS_TMR_OPT_NONE 0u 沒有選擇
    #define OS_TMR_OPT_ONE_SHOT 1u 定時器不會自動重復使用
    #define OS_TMR_OPT_PERIODIC 2u 定時器會自動重裝
    #define OS_TMR_OPT_CALLBACK 3u OSTmrStop()中使用,調用回調函數,但不帶參數
    #define OS_TMR_OPT_CALLBACK_ARG 4u 也是OSTmrStop()中使用,調用回調函數,但有參數。
    1. Callback 指向回調函數的指針,這個函數這樣聲明,void mycallback(OS_TMR *ptmr, void p_arg );
    2. Callback_arg 參數給callback的。
    3. Pname 定時器的名字
    4. Perr 錯誤指針* OS_ERR_NONE 沒有錯誤
    OS_ERR_TMR_INVALID_DLY 無效的定時時間
    OS_ERR_TMR_INVALID_PERIOD 無效的周期
    OS_ERR_TMR_INVALID_OPT 無效的選項
    OS_ERR_TMR_ISR 在中斷中調用
    OS_ERR_TMR_NON_AVAIL 空的定時器用光了,這個和task一樣意思。
    用到的函數OSTmr_Alloc()得到一個定時器結構體。
    二、刪除一個定時器,也是在我們的功能函數中使用,返回為是否成功刪除。
    BOOLEAN OSTmrDel (OS_TMR *ptmr,
    INT8U *perr)
    1. Ptmr 指向定時器結構體。
    2. Perr 指向錯誤的指針。
    這里用到這兩個函數OSTmr_Unlink(ptmr); 如果是定時器在工作時,要用它解除 OSTmrState= OS_TMR_STATE_STOPPED。
    OSTmr_Free(ptmr); 釋放這個定時器結構體。
    三、得到定時器名字的函數,返回名字的長度。
    INT8U OSTmrNameGet (OS_TMR *ptmr,
    INT8U **pdest, 指向了一個指向定時器名字地址指針的指針。
    INT8U *perr)
    四、定時器還有多長時間溢出。返回還有多長時間溢出。
    INT32U OSTmrRemainGet (OS_TMR *ptmr,
    INT8U *perr)
    五、獲得定時器狀態的函數,返回狀態。
    INT8U OSTmrStateGet (OS_TMR *ptmr,
    INT8U *perr)
    六、啟動你的定時器,返回是否成功啟動。 你的應用程序使用它
    BOOLEAN OSTmrStart (OS_TMR *ptmr, 要用到OSTmr_Unlink()和OSTmr_Link()先
    INT8U *perr)散 解除,再重新用這個定時器
    七、停止定時器,返回是否成功停止。 你的應用程序使用它
    BOOLEAN OSTmrStop (OS_TMR *ptmr,
    INT8U opt,
    void *callback_arg, 這個也是個函數
    INT8U *perr)
    回調函數在這里使用,callback()。
    Opt 為OS_TMR_OPT_NONE不使用回調函數。
    OS_TMR_OPT_CALLBACK使用回調函數不用參數。
    OS_TMR_OPT_CALLBACK_ARG要使用參數。
    八、發送信號,這個是在timer tick中使用要您寫到ISR中
    INT8U OSTmrSignal (void)返回信號量
    九、從定時器池中得到一個結構體。在建構函數中用
    static OS_TMR *OSTmr_Alloc (void);
    十、釋放定時器,中刪除函數中用
    static void OSTmr_Free (OS_TMR *ptmr)
    十一、OSTmr_Init(void),在OSInit()中用。
    十二、static void OSTmr_InitTask (void)在OSTmr_Init中使用。用來建立一個任務OSTmr_Task()
    十三、OSTmr_Task()這個是調度你建立的定時器用的,一但定時時間到就調用回調函數。
    我們建立的定時器都進入定時器輪盤里OSTmrWheelTbl[],
    十四、static void OSTmr_Link (OS_TMR *ptmr, //OSTmrState = OS_TMR_STATE_RUNNING
    INT8U type)
    Ptmr->OSTmrMatch的確定方法
    if (type == OS_TMR_LINK_PERIODIC) {
    ptmr->OSTmrMatch = ptmr->OSTmrPeriod + OSTmrTime;
    } else {
    if (ptmr->OSTmrDly == 0) {
    ptmr->OSTmrMatch = ptmr->OSTmrPeriod + OSTmrTime;
    } else {
    ptmr->OSTmrMatch = ptmr->OSTmrDly + OSTmrTime;
    }
    }
    掛載定時器時spoke = (INT16U)(ptmr->OSTmrMatch % OS_TMR_CFG_WHEEL_SIZE);
    pspoke = &OSTmrWheelTbl[spoke];這樣確定的置位,當OSTmrTime加到和OSTmrMatch相等時一定會來以這個spoke為下標的數組里找該定時器。至于定義一個OSTmrWheelTbl[]而不是把你所有建立的定時器串成一串是怕一起處理浪費時間吧,這樣可以一次少處理幾個定時器。
    我想看了OSTmr_Task (void *p_arg)這個函數的人可能會好奇為什么用那種方法掛載定時器,當定時時間到了時會找到OSTmrWheelTbl[]正確的下標,并在那個OSTmrWheelTbl[ok]里找到該定時器吧。其實你可以算一下,定義OS_TMR_CFG_WHEEL_SIZE=8,然后在OSTmrTime=6時建立一個定時器(假如定時器只工作一次),OSTmrDly=12,那個這個定時器會掛到OSTmrWheelTbl[2]中,當OSTmrTime加到18時它就會去
    OSTmrWheelTbl[2]找該定時器。
    十五、static void OSTmr_Unlink (OS_TMR *ptmr)釋放定時器結構體用它把該定時器從定時器輪中卸下。


    關鍵詞: ucosos_tmrc代碼分

    評論


    技術專區

    關閉
    主站蜘蛛池模板: 呼玛县| 泸州市| 资中县| 安庆市| 连南| 泰宁县| 神木县| 英山县| 景东| 山阳县| 客服| 抚顺县| 佛坪县| 赫章县| 安国市| 青铜峡市| 广饶县| 保德县| 新巴尔虎右旗| 寿光市| 云阳县| 宜兰市| 甘南县| 兴业县| 巴楚县| 北安市| 东辽县| 庆元县| 淮安市| 闻喜县| 庆城县| 子长县| 嵊泗县| 安西县| 翁牛特旗| 松桃| 当雄县| 前郭尔| 深水埗区| 五华县| 西林县|