📄 conf_tny.a51
字号:
$NOMOD51
;------------------------------------------------------------------------------
; This file is part of the RTX-51 TINY Real-Time Operating System Package
; Copyright KEIL ELEKTRONIK GmbH and Keil Software, Inc. 1991-2002
; Version 2.01
;------------------------------------------------------------------------------
; CONF_TNY.A51: This code allows the configuration of the
; RTX-51 TINY Real-Time Operating System
;
; Copy this file to your project folder and add the copy to your uVision2
; project. You can customize several parameters of RTX51 Tiny within this
; configuration file.
;
; If you use command line tools, translate this file with:
;
; Ax51 CONF_TNY.A51
;
; If you use command line tools, link the modified CONF_TNY.OBJ file to
; your application with:
;
; Lx51 <your object file list>, CONF_TNY.OBJ <controls>
;
;------------------------------------------------------------------------------
;=============================================================
; RTX-51 TINY 硬件时钟
;-------------------------------------------------------------
; 定义时钟中断所使用的寄存器组.
; 只用到 BANK1 的5个字节
INT_REGBANK EQU 1 ; 缺省为寄存器组 1
;
;=============================================================
; 定义硬件时钟频率, 为多少个 8051 的机器周期
;-------------------------------------------------------------
; 公式: (XTAL / CLOCK) / (1000 / SEP)
; (18432000/ 6) / 100 = 30720 =10ms
; (11059200/ 6) / 100 = 18432 =10ms
CPU_XTAL EQU 11059200 // 8051 晶振频率,单位Hz
FREQ_TIME EQU 10 // ms
INT_CLOCK EQU (CPU_XTAL / 6) / (1000 / FREQ_TIME) ; default is 10000 cycles
;
;=============================================================
; 当用户的中断执行时间大于 RTX51 的时钟中断执行时间则 LONG_USR_INTR = 1
;-------------------------------------------------------------
LONG_USR_INTR EQU 1 ; 0 用户中断快速执行时.
; ; 1 用户中断需要很长时间执行.
;=============================================================
; 最大任务数, 不包含 TASK_INIT
;-------------------------------------------------------------
RTX_MAXTASKN EQU 6
;
;=============================================================
; 硬件时钟代码, 该代码插入到 RTX51 TINY 的时钟中断
;-------------------------------------------------------------
HW_TIMER_CODE MACRO
; Empty Macro by default
RETI
ENDM
;=============================================================
; RTX-51 TINY 栈空间
;-------------------------------------------------------------
RAMTOP_NEW EQU 0 ; 扩展栈空间到 89C669
RAMTOP EQU 0FFH ; 用来标记堆栈的顶部 (256-1)
;
FREE_STACK EQU 0 ; 缺省为20字节的剩余栈空间,该值为零则关闭剩余栈检查
;
;-------------------------------------------------------------
;剩余栈空间不足时执行宏 STACK_ERROR
STACK_ERROR MACRO
CLR EA ; 关闭中断
SJMP $ ; 如果栈空间耗尽进入无限循环
ENDM
;
;
;=============================================================
; 8051 CPU 空闲模式
;-------------------------------------------------------------
; 空闲代码可以降低功耗与 EMC, 当系统无就绪任务时执行以下代码
CPU_IDLE_CODE EQU 0 ; 0 关闭空闲模式
; 1 打开空闲模式
;-------------------------------------------------------------
; 空闲模式代码
PCON DATA 087H ; 控制寄存器 SFR
CPU_IDLE MACRO
ORL PCON,#1 ; set 8051 CPU to IDLE
ENDM
;
;
;------------------------------------------------------------------------------
;----------------- !!! End of User Configuration Part !!! ------------------
;----------------- !!! Do not modify code sections below !!! ------------------
;------------------------------------------------------------------------------
; SFR Symbols
PSW DATA 0D0H
ACC DATA 0E0H
B DATA 0F0H
SP DATA 81H
//SPE DATA 0x1FB
DPL DATA 82H
DPH DATA 83H
TCON DATA 88H
TMOD DATA 89H
TL0 DATA 8AH
TL1 DATA 8BH
TH0 DATA 8CH
TH1 DATA 8DH
IE DATA 0A8H
; TCON
TF1 BIT 8FH
TR1 BIT 8EH
TF0 BIT 8DH
TR0 BIT 8CH
IE1 BIT 8BH
IT1 BIT 8AH
IE0 BIT 89H
IT0 BIT 88H
; IE
EA BIT 0AFH
ES BIT 0ACH
ET1 BIT 0ABH
EX1 BIT 0AAH
ET0 BIT 0A9H
EX0 BIT 0A8H
; Check Configuration Values
NAME ?RTX51_TINY_KERNAL
PUBLIC ?RTX_CURRENTTASK
PUBLIC ?RTX_RAMTOP
PUBLIC os_switch_task
PUBLIC ?RTX?SET_ISR
PUBLIC ?RTX_MAXTASKN
;------------------------------------------------
; 任务入口地址表 定义在 MAIN.C
EXTRN HCONST (TASK_ENTRY)
;------------------------------------------------
; 最大任务数, 不包含 TASK_INIT
?RTX_MAXTASKN EQU RTX_MAXTASKN
/* 重新定义 */
IF(RAMTOP_NEW == 0)
?RTX_RAMTOP EQU RAMTOP
ENDIF
?RTX_CLOCK EQU -INT_CLOCK
?RTX_REGISTERBANK EQU INT_REGBANK * 8
DSEG AT ?RTX_REGISTERBANK
DS 2 ; temporary space
?RTX_SAVEACC: DS 1
saveacc EQU R2 ; for access in interrupt service routine
?RTX_SAVEPSW: DS 1
savepsw EQU R3 ; for access in interrupt service routine
?RTX_CURRENTTASK: DS 1
currenttask EQU R4 ; for access in interrupt service routine
;------------------------------------------------
; Table of Stack Pointers for each task
;------------------------------------------------
PUBLIC ?RTX_TASKSP
?RTX?TASKSP?S SEGMENT IDATA
RSEG ?RTX?TASKSP?S
?RTX_TASKSP: DS 1
DS 1 * ?RTX_MAXTASKN
;------------------------------------------------
; Table of Task Timer/State Pointers
;------------------------------------------------
PUBLIC ?RTX_TASKSTATUS
?RTX?TASKSTATE?S SEGMENT IDATA
RSEG ?RTX?TASKSTATE?S
?RTX_TASKSTATUS:
TimerVal: DS 1 ; Task Timer (Software Timer for each task)
TaskState: DS 1 ; Task Status (state of each Task)
DS 2 * ?RTX_MAXTASKN
; Definitions for Bits in Task State
; TaskState.0 = Wait for Signal
; TaskState.1 = Wait for TimeOut
; TaskState.2 = Signal Flag
; TaskState.3 = TimeOut Flag
; TaskState.4 = Task Ready (Wait for Running)
; TaskState.5 = Task Active (enabled with os_create)
; TaskState.6 = Round Robin Time Out
; TaskState.7 = Run Flag
; byte mask definitions
IF(RAMTOP_NEW == 1)
PUBLIC ?RTX_TASK_EI
?RTX?TASKENTI?S SEGMENT IDATA
RSEG ?RTX?TASKENTI?S
?RTX_TASK_EI: DS 12
;------------------------------------------------
?RTX_RAMTOP EQU ?RTX_TASK_EI + 12*7
ENDIF
K_SIG EQU 1
K_TMO EQU 2
SIG_EVENT EQU 4
TMO_EVENT EQU 8
K_READY EQU 16
K_ACTIVE EQU 32
K_IVL EQU 128 ; not a task state bit; only used in os_wait
RDY_EVENT EQU 128 ; READY status flag
K_RDY EQU 128 ; READY status flag
; bit position definitions
B_WAITSIG EQU 0
B_WAITTIM EQU 1
B_SIGNAL EQU 2
B_TIMEOUT EQU 3
B_READY EQU 4
B_ACTIVE EQU 5
B_ROBIN EQU 6
B_IVL EQU 7 ; not a task state bit; only used in os_wait
B_RDY EQU 7
IF (CPU_IDLE_CODE)
?RTX?BITS SEGMENT BIT
RSEG ?RTX?BITS
ENDIF
IF (CPU_IDLE_CODE)
?RTX_ISR_SIG: DBIT 1 ; Status bit set when interrupt or os_set_signal
ENDIF
/* ====================================================================== */
/* 时钟中断处理 */
CSEG AT 0BH
EJMP TIMERINT
?RTX?CODE SEGMENT ECODE
RSEG ?RTX?CODE
USING 0 ; Registerbank 0 for following code
IF (FREE_STACK <> 0)
?RTX_STACKERROR:
STACK_ERROR ; User defined Stack Error Code
ENDIF
HW_TIMER: HW_TIMER_CODE
TIMERINT:
IF (LONG_USR_INTR)
PUSH ACC
MOV A,PSW
ANL A,#018H
XRL A,#?RTX_REGISTERBANK
JNZ CONT_TIMINT
; 避免递归调用时钟中断
POP ACC
RETI ; Return from Recursive Timer Interrupt
CONT_TIMINT: POP ACC
ENDIF
//ECALL HW_TIMER ; Enable Interrupts again.
MOV ?RTX_SAVEPSW,PSW
MOV PSW,#?RTX_REGISTERBANK
MOV saveacc,A
/* ------------------------------------------------------------ */
; 更新 8051 时钟中断重载值,
CLR TR0
MOV A,TL0
ADD A,#LOW (?RTX_CLOCK + 7)
MOV TL0,A
MOV A,TH0
ADDC A,#HIGH (?RTX_CLOCK + 7)
MOV TH0,A
SETB TR0
; -----------------------------------------------------------
IF (FREE_STACK <> 0)
; 栈空间检查
MOV A,currenttask
ADD A,#?RTX?TASKSP?S+1
MOV R0,A
MOV A,@R0
CJNE currenttask,#?RTX_MAXTASKN,checkstack
MOV A,#?RTX_RAMTOP
checkstack: CLR C
SUBB A,SP
CJNE A,#FREE_STACK,$+3
JC ?RTX_STACKERROR
ENDIF
; Update & Check Task Timers
MOV R1,#?RTX_MAXTASKN+1
MOV R0,#?RTX?TASKSTATE?S
TIMERLOOP:
/* ------------------------------------------------------------ */
; 每次时钟中断对所有任务的计时器减一
DEC @R0 ; Decrement timer
MOV A,@R0
INC R0 ; advance to TaskState
JNZ NoTimeout
CLR EA
MOV A,@R0
/* ------------------------------------------------------------ */
; 如果任务在等待超时则处理, 如果在等待信号则立即返回
JNB ACC.B_WAITTIM,NoWaitTimeout
ORL A,#(K_READY+TMO_EVENT)
MOV @R0,A
NoWaitTimeout:
SETB EA
NoTimeout:
INC R0 ; advance to TaskTimer
DJNZ R1,TIMERLOOP
MOV A,saveacc
MOV PSW,savepsw
USING 0 ; Registerbank 0 for following code
?RTX?SET_ISR:
IF (CPU_IDLE_CODE)
SETB ?RTX_ISR_SIG
ENDIF
RETI
/* ====================================================================== */
; 任务切换主过程, 所有的任务函数执行最终转到这里执行
; void os_switch_task (void)
; uchar i;
; uchar limit;
;
;---- current = R6
;---- next = R7
;---- i = R0
;---- limit = R5
;------------------------------------------------
os_switch_task:
os_switch_task1:
; next = current;
MOV A,?RTX_CURRENTTASK
MOV R7,A
/* ------------------------------------------------------------------------
?RTX_CURRENTTASK + 1 => ?RTX_CURRENTTASK 循环判断是否有任务处于就绪状态
通常调用 os_switch_task 的任务,本身已经处于就绪态, 故当无其它就绪任务后,
将直接返回到 ?RTX_CURRENTTASK
*/
; while (1) {
RL A
ADD A,#?RTX?TASKSTATE?S+1
MOV R0,A
?C0001:
; if (++next == MAXTASKN+1) next = 0;
INC R7 /* ++R7, 同时++?RTX?TASKSTATE?S */
INC R0 /* R7=任务号; R0 指向该任务的状态字节 */
INC R0
IF (CPU_IDLE_CODE)
MOV A,R7
CJNE A,?RTX_CURRENTTASK,NoIDLE
JBC ?RTX_ISR_SIG,NoIDLE
CPU_IDLE ; CPU sleep
NoIDLE:
ENDIF
CJNE R7,#?RTX_MAXTASKN+1,?C0003
MOV R7,#0
MOV R0,#?RTX?TASKSTATE?S+1
?C0003:
; if (STATE[next].st & K_READY) break;
MOV A,@R0
JNB ACC.B_READY,?C0001
; }
/* ------------------------------------------------------------------------
查找到就绪的任务后,转到此过程进行任务切换
*/
; while (current < next) {
?C0005:
MOV A,?RTX_CURRENTTASK
CLR C
SUBB A,R7
JNC ?C0011
; current++;
INC ?RTX_CURRENTTASK
; i = STKP[current];
MOV A,#?RTX?TASKSP?S
ADD A,?RTX_CURRENTTASK
MOV R0,A
MOV A,@R0
MOV R5,A
; STKP[current] = SP;
MOV @R0,SP
; if (current == MAXTASKN) limit = RAMTOP;
INC R0
MOV A,@R0
MOV R6,?RTX_CURRENTTASK
CJNE R6,#?RTX_MAXTASKN,?C0007
MOV A,#?RTX_RAMTOP
?C0007:
XCH A,R5
MOV R0,A
; else limit = STKP[current+1];
;
; while (i != limit) {
?C0009:
MOV A,R0
XRL A,R5
JZ ?C0005
; SP++;
; i++;
; STACK[SP] = STACK[i];
INC R0
MOV A,@R0
PUSH ACC
SJMP ?C0009
; }
; }
?C0011:
;
; while (current > next) {
MOV A,?RTX_CURRENTTASK
SETB C
SUBB A,R7
JC ?C0012
MOV A,?RTX_CURRENTTASK
ADD A,#?RTX?TASKSP?S+1
MOV R0,A
MOV A,@R0
; if (current == (MAXTASKN)) i = RAMTOP;
; else i = STKP[current+1];
MOV R6,?RTX_CURRENTTASK
CJNE R6,#?RTX_MAXTASKN,?C0013
MOV A,#?RTX_RAMTOP
?C0013:
MOV R5,A
; limit = STKP[current];
DEC R0
MOV A,@R0
XCH A,R5
MOV R0,A
;
; while (SP != limit) {
?C0015:
MOV A,SP
XRL A,R5
JZ ?C0016
; STACK[i] = STACK[SP];
; i--;
; SP--;
POP ACC
MOV @R0,A
DEC R0
SJMP ?C0015
?C0016:
; }
; STKP[current] = i;
MOV A,?RTX_CURRENTTASK
ADD A,#?RTX?TASKSP?S
XCH A,R0
MOV @R0,A
; current--;
DEC ?RTX_CURRENTTASK
SJMP ?C0011
?C0012:
; }
MOV A,?RTX_CURRENTTASK
RL A
ADD A,#?RTX?TASKSTATE?S+1
MOV R0,A
MOV R7,#SIG_EVENT
CLR EA
MOV A,@R0
; if ((STATE[current].st & K_SIG) && (STATE[current].st & SIG_EVENT)
; goto SignalOn;
JNB ACC.B_WAITSIG,SignalOff
JBC ACC.B_SIGNAL,SignalOn
SignalOff:
; if ((STATE[current].st & K_TMO) && (STATE[current].st & TMO_EVENT)
; goto TimeOutOn;
MOV R7,#0 ; No Event
JNB ACC.B_WAITTIM,NoEvent
JNB ACC.B_TIMEOUT,NoEvent
TimeOutOn:
MOV R7,#TMO_EVENT
ANL A,#0F4H
SignalOn:
NoEvent: CLR ACC.B_RDY ; Clear RDY bit
XCH A,@R0
SETB EA
ANL A,#K_RDY
ORL AR7,A
ERET
; }
; }
/* ====================================================================== */
; 启动 RTX-51 Tiny 内核
;------------------------------------------------------------------------
EXTRN CODE (?C_STARTUP)
PUBLIC main
main: MOV R0,#?RTX?TASKSP?S
MOV @R0,SP /* ?RTX?TASKSP?S 与 堆栈 SP对齐 */
MOV A,#?RTX_MAXTASKN
JZ main2
MOV R7,A
main1: INC R0
MOV @R0,#?RTX_RAMTOP
DJNZ R7,main1
main2: MOV R7,#?RTX_MAXTASKN+1
CLR A
MOV R0,#?RTX?TASKSTATE?S
main1x: MOV @R0,A
INC R0
MOV @R0,A
INC R0
DJNZ R7,main1x
MOV R0,#?RTX?TASKSTATE?S+1
MOV @R0,#K_ACTIVE+K_READY
/* ------------------------------------------------------------------------
压入任务 TASK_INIT 的入口地址
*/
MOV EPTR,#TASK_ENTRY
MOV A,#2
MOVC A,@A+EPTR
PUSH ACC
MOV A,#1
MOVC A,@A+EPTR
PUSH ACC
CLR A
MOVC A,@A+EPTR
PUSH ACC
/* ------------------------------------------------------------------------ */
ORL TMOD,#01H ; Timer 0 Mode 1
MOV TL0,#LOW (?RTX_CLOCK)
MOV TH0,#HIGH (?RTX_CLOCK)
SETB TR0
SETB EA
SETB ET0
; 弹出任务 TASK_INIT
ERET ; Start Task 0
/* ------------------------------------------------------------------------ */
//PUBLIC ?RTX_TASKIDX
//?RTX_TASKIDX: DB ?RTX_MAXTASKN ; for Debugging
END
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -