This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

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.

  • 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

  • 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

  • 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

  • Move CALL HW_TIMER after last line you posted.
    Roman

  • I didn't want to screw up the order of things, so I left the CALL HW_TIMER where it was.