⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 conf_tny.a51

📁 让Keil 的 RTX51 运行在 P89C669 让Keil 的 RTX51 运行在 P89C669
💻 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 + -