參考文檔 :RTX51 Tiny 2.02 中文手冊.doc、Keil_Rtx51_tiny_RTOS中文版.pdf
RTX-51 有 2 個版本:Full 和 Tiny。類似的國人寫的 Small RTOS51。
Full 需要的資源較多(8K ROM/450的XDATA),但支持搶占式任務調度和中斷任務,以及任務間互發消息;Tiny 不支持搶占式調度,任務間也不能互發消息,但消耗資源少(7+3*任務數RAM/不占用XDATA)。注意對C8051F/STC類增強型51用large模式
參考資料見《RTX51 Tiny第2版用戶手冊》
2類庫文件
RTX51TNY.LIB 用於無代碼分組 (non_banking) 的 RTX51 Tiny 程序。
RTX51BT.LIB用於代碼分組(code_ banking 的 RTX51 Tiny 程序。
一 特點:只適合51系列的周期性的任務場合(C8051F/STC),最多16個任務,沒有主函數,從_task_ 0開始(用於創建其它任務,然后將自己刪除,除_task_ 0外其它都是while(1)死循環),結構小巧只需要包含#include <rtx51tny.h>並在工程配置中選擇。且需要項目添加CONF_TNY.A51,占用了定時器0和寄存器組1.
Memory Model 用 Small 比較好,免得每次聲明變量都寫 data 修飾
二系統滴答:
-
配置文件ConfTny.A51中INT_CLOCK EQU 10000; default is 10000 cycles,意思是時鍾滴答為10000個機器周期,即10000*1uS=10ms。所以
os_wait(K_TMO, T, 0)定時時間=T*10MS;
;定時器時鍾選擇為系統時鍾;因為C51是12T(一個單機器周期nop指令需要12個時鍾周期/震盪周期(1/fs)),所以機器周期=12/fs(us).
;fs=12M;0.001s*12000000=12000
;fs=24M;0.001s*24000000=24000
;fs=48M;0.001S * 48000000 = 48000
INT_CLOCK EQU 24000 ; default is 10000 cycles -
TIMESHARING,即循環任務切換每個任務分到時間片,完了該任務被掛起切到其它就緒任務。默認是 5(5* INT_CLOCK),從這點來說Tiny-51適合 周期性任務的場合,如果這個值是 0,那么,Round Robin 的任務輪詢算法會停止,必須你自己手動 os_send_signal 或者 os_switch_task 來切換任務。某些時候,這樣會提高實時性
- RAMTOP。指定了可用 RAM 的頂部地址,默認是 0FFH,即 256 字節 RAM,任務多時要改小些
- 任務若由時間片被動調度,修改時間的方法https://www.cnblogs.com/lizunicon/archive/2009/05/19/1460549.html
-
我的程序要對一個脈寬30ms左右的脈沖計數,結果開始總是不對,后來才找到毛病。
改配置文件的方法:
1. 打開D:"Keil"C51"RTX_TINY目錄下CONF_TNY.A51文件,修改兩個參數
2. 執行相同目錄下的genrtx.bat文件,執行成功后會生成Rtx51tny.lib文件
3. 將D:"Keil"C51"LIB下的Rtx51tny.lib作個備份,再將第2步中生成的Rtx51tny.lib拷貝到D:"Keil"C51"LIB目錄下覆蓋原有文件即可
4. 重新編譯你的工程
- 如果使用timesharing,則一個延時函數的執行時間=(Tint+Ttimesharing)*任務數+delay/fos
任務的狀態:
1 運行態(running)
:只有一個
2 就緒態(read):通過調用延時函數后超時就處於該狀態
3.阻塞(blocked):調用延時函數但未超時,或者調用任務切換函數后的狀態。
4 休眠(sleeping):任務聲明但未使用或者已經刪除過的任務。
任務的主動切換:
void os_switch_task (void)//同時切換到的任務必須就緒,否則也不能運行。
os_delete和os_wait
主動設置任務就緒:用 os_set_ready 和 isr_set_ready 函數,用於讓那些等待超時、時間間隔、等待信號的任務設置就緒標志以運行
任務間通訊:用 os_send_signal 和isr_send_signal 函數
關於os_wait
的三類參數:K_TMO、K_IVL和K_SIG,可以是前兩個與信號的組合(或邏輯)。其返回值表明發生的事件,SIG_EVENT( 由os_send_signal 和isr_send_signal
產生),RDY_EVENT(由 os_set_ready 或 isr_set_ready引起
) TMO_EVENT(由超時或時間間隔到達引起)
延時的實際時間只與基本時間片INT_CLOCK有關,與timesharing無關(而任務的執行時間=timesharing/INT_CLOCK
).延時函數只是延遲一定時間后讓其就緒並不保證它馬上運行,所以真正的延時時間還與當前執行任務的狀況和總的任務數有關。
K_TMO:超時信號不累計,在任務重的時候可能誤差較大
K_IVL:周期信號,可累計保證信號不丟失。
K_SIG
任務的獨占:
方法1:禁止循環任務調度調度:TIMESHARING=0(適應於實時性不高)、關中斷(EA=0/關TO中斷但時間不能太長)
方法2:模仿FULL_RTX51編寫申請和釋放信號量,參考 https://blog.csdn.net/dkr269944905/article/details/72822959
注意事項:
1高優先級中斷任務執行執行過長:原則高優先級中斷的ISR應該盡量簡潔(避免系統滴答中斷的重入),或者讓系統滴答的周期中斷時間長一些(但這樣實時性不好);最好的方法是LONG_USR_ISR=1,此時OS就會保護再入系統滴答中斷的代碼當然會增加開銷。
2 空閑任務:SJMP $ //某些兼容的8051有低功耗模式,tinyos支持低功耗,在定時器滴答中斷或者其它中斷時MCU恢復運行。 CPU_IDLE 宏 其實就是置位PCON的空閑模式位降低功耗
3 優化:盡可能禁止循環任務切換,而主動使用os_switch_task
、os_wait
來主動切換降低13個字節的棧空間保護,同時避免系統滴答周期太快,任務從0開始。
三 函數:
3.1 創建任務:os_create_task(taskID
);
,對應的刪除任務os_delete_task (taskID
);而具體的任務函數時無參數無返回的
3.2發送信號:char isr_send_signal(unsigned char task_id)、 os_send_signal/os_clear_signal ,前者由中斷函數使用,返回-1表示任務不存在,0表示成功。
3.3設置就緒:char isr_set_ready{ unsigned char task_id} 、os_set_ready
3.4任務的切換:char os_switch_task(void)
3.5等待:char os_wait1(unsigned char event_sel) 、char os_wait2(unsigned char event_sel, /* 要等待的事件 */unsigned char ticks);
char os_wait(
unsigned char event_sel, /* 要等待的事件 */
unsigned char ticks, /* 要等待的滴答數 */
unsigned int dammy) ,前者只能等待信號是后者的簡化版
3.4糾正當任務調用OS_Wait(K_IVL| K_SIG )同時等待一個信號和周期任務,在 K_SIG
到達OS_Wait退出而時間間隔並沒有調整而引起后續調用OS_Wait的時間不准問題,:void os_reset_interval(unsigned char ticks) ,使用方法:
switch(os_wait2(KSIG|K_IVL,100))
{
case TMO_EVENT:
/* 發生了超時,不需要 Os_reset_interval*/
break;
case SIG_EVCENT:
/* 收到信號,需要 Os_reset_interval*/
os_reset_interval(100);
/* 依信號執行的其它操作 */
break;
}
… 3.5增加任務優先級?http://bbs.21ic.com/icview-309676-1-1.html
四調試:
從 Peripherals 菜單選擇 RTX51 Tiny T asklist 顯示該對話框 TID 是在任務定義中指定的任務 ID。
Task Name 是任務函數的名字。
State 是任務當前的狀態。
Wait for Event 指出任務正在等待什么事件。
Sig 顯示任務信號標志的狀態( 1 為置位)。
Timer 指示任務距超時的滴答數, 這是一個自由運行的定時器, 僅在任務等待超時和時間間隔時使用。
Stack 指示任務棧的起始地址。