Discussion Forum

Problem with SI-Labs Special Function Registers and RTX51Tiny

Next Thread | Thread List | Previous Thread Start a Thread | Settings

DetailsMessage
Read-Only
Author
Paul Blase
Posted
7-Aug-2005 04:22 GMT
Toolset
C51
New! Problem with SI-Labs Special Function Registers and RTX51Tiny
I'm wondering if anybody else has run into a problem with RTXTiny51 and the SiLabs processor. I'm using the C8052F62 processor, am using a LOT of the peripherals and have IO lines and interrupt routines all over the place. The SiLabs devices, having a lot of peripherals, have paged Special Function Registers, and - the crux of the difficulty - have a neat little stack mechanism for storing the current SFR page and automatically setting the proper one during an interrupt. The SRF page pointer is pushed onto a special hardware stack at an interrupt and popped again at the next RTI.
RTXTiny not being optimized for the SI Labs processors and the SFRPAGE register, one has to set the SFRPAGE to page 0 before making any RTXTiny Call so that it will talk properly to the Timer 0. So far, so good. A tech note suggests setting the SFR page before any Timer 0 accesses in Conf_tny.A51, but there's a problem with that as discussed below.
I've been chasing down another rather subtle problem and the fix has me stymied. The RTX51Tiny timer call is entered, obviously enough, with an interrupt by the Timer 0 overflow. If you look carefully at the code in Conf_Tny.A51 the return from the user code (the macro at the top into which one can stick your own stuff to be executed every clock tick) at the top of the file returns with an RETI; more stuff having to do with checking the status of suspended tasks is executed further down and then the routine returns to whence it came originally with a RET.
This all means that if the timer interupt happens to occur just after you've set the SFR register to something other than 0, the SFR page is popped from the NEXTSFR register into the SFRPAGE register prematurely - at the return from the user code macro - and screws up the TR0 calls in the rest of the task-checking code. If you follow the tech-note suggestion and set the SFRPAGE to 0 at each Timer 0 function, then it won't be correct (again, if the interrupt happens after you've set the SFRPAGE but before you've actually used it) when the interrupt returns to the original code.
The code is rather complex, there are interactions with the task management system, and swapping the RETI and RET commands around ends up with the program in an infinite loop the first time that you call an RTX51 wait() function. I need to investigate further, but seems like something causes the interrupt to talk to the wrong register page.
Any assistance would be appreciated.
Read-Only
Author
Reinhard Keil
Posted
5-Sep-2005 18:01 GMT
Toolset
C51
New! RE: Problem with SI-Labs Special Function Registers and RTX51Tiny
Paul, sorry for being so late on this issue. However, we would like to get a better understanding for the problem.

Disabling Round-Robin scheduling and setting the SFRPAGE to 0 before calling an RTX51 Tiny function should do the job. When you are doing this, do you still encounter problems?

Reinhard
Read-Only
Author
roman horvath
Posted
8-Sep-2005 10:00 GMT
Toolset
C51
New! RE: Problem with SI-Labs Special Function Registers and RTX51Tiny
Yes, if you diasable everythink you'll have no problem. Or try to move call to hw_timer(with its RETI) after the all timer 1 acces code(timer1 update code) in conf_tny file. I look only briefly in the conf_tny file but maybe helps.
Roman
Read-Only
Author
Paul Blase
Posted
8-Sep-2005 15:22 GMT
Toolset
C51
New! RE: Problem with SI-Labs Special Function Registers and RTX51Tiny
Actually, disabling everything _won't_ solve the problem. The problem is that the user HW_TIMER_CODE's RTI at the end of the Macro does not return to the user code but goes instead to Update 8051 Interrupt Timer code which returns to the user code with an RET. The RTI pops the SFRPAGE stack too soon, leaving it on the wrong page for the subsequent calls to Timer 0.

Here is my code with patches:

...
; SFR Symbols
PSW DATA 0D0H
ACC DATA 0E0H
B DATA 0F0H
SP DATA 81H
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
SFRPAGE DATA 84H ;BLASE 8/1/05

CONFIG_PAGE EQU 0x0F ;BLASE 8/22/05
LEGACY_PAGE EQU 0x00 ;BLASE 8/22/05
TIMER01_PAGE EQU 0x00 ;BLASE 8/22/05


; 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

EXTRN NUMBER (?RTX_MAXTASKN) ; max Task Number

?RTX_RAMTOP EQU RAMTOP
?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

EXTRN DATA (RTX_SFRStorage) ;BLASE 8/22/05, for temporary storage of SFR

IF (TIMESHARING <> 0)
?RTX_ROBINTIME: DS 1
robintime EQU R5 ; for access in interrupt service routine
ENDIF

IF (CODE_BANKING <> 0)
EXTRN DATA (?B_CURRENTBANK)
EXTRN CODE (?B_RESTORE_BANK)
ENDIF


;------------------------------------------------
; Table of Task Entry Pointers
;------------------------------------------------
PUBLIC ?RTX_TASKENTRY

?RTX?TASKENT?S SEGMENT CODE
RSEG ?RTX?TASKENT?S
?RTX_TASKENTRY: DS 2

;------------------------------------------------
; Table of Stack Pointers for each task
;------------------------------------------------
PUBLIC ?RTX_TASKSP

?RTX?TASKSP?S SEGMENT IDATA
RSEG ?RTX?TASKSP?S
?RTX_TASKSP: DS 1

;------------------------------------------------
; 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)

; 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
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_ROBIN EQU 64
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

; 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 (TIMESHARING OR CPU_IDLE_CODE)
?RTX?BITS SEGMENT BIT
RSEG ?RTX?BITS
ENDIF

IF (TIMESHARING)
?RTX_TS_DELAY: DBIT 1 ; Status bit set when task switch in progress
ENDIF

IF (CPU_IDLE_CODE)
?RTX_ISR_SIG: DBIT 1 ; Status bit set when interrupt or os_set_signal
ENDIF


CSEG AT 0BH
JMP TIMERINT

?RTX?CODE SEGMENT CODE
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
; avoid recursive timer interrupt
POP ACC
RETI ; Return from Recursive Timer Interrupt
CONT_TIMINT: POP ACC
ENDIF

CALL HW_TIMER ; Enable Interrupts again.

MOV ?RTX_SAVEPSW,PSW
MOV PSW,#?RTX_REGISTERBANK
MOV saveacc,ACC ; ACC required by some Cygnal devices

; Update 8051 Interrupt Timer
MOV RTX_SFRStorage, SFRPAGE ;Blase 8/22/05 - store SFRPAGE from whatever was interrupted
MOV SFRPAGE, #TIMER01_PAGE ;Blase 8/22/05 - Use TIMER01_PAGE

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
MOV SFRPAGE, RTX_SFRStorage ;Blase 8/22/05 - put the current SFR page back
Read-Only
Author
roman horvath
Posted
9-Sep-2005 10:20 GMT
Toolset
C51
New! RE: Problem with SI-Labs Special Function Registers and RTX51Tiny
Move CALL HW_TIMER after last line you posted.
Roman
Read-Only
Author
Reinhard Keil
Posted
13-Sep-2005 13:15 GMT
Toolset
C51
New! RE: Problem with SI-Labs Special Function Registers and RTX51Tiny
We have another variant for this:
http://www.keil.com/support/docs/3104.htm

Reinhard
Read-Only
Author
Paul Blase
Posted
13-Sep-2005 19:54 GMT
Toolset
C51
New! RE: Problem with SI-Labs Special Function Registers and RTX51Tiny
I didn't want to screw up the order of things, so I left the CALL HW_TIMER where it was.

Next Thread | Thread List | Previous Thread Start a Thread | Settings