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

📄 avrx_semaphores.s

📁 血凝仪检测系统,硬件电路部分由正弦波产生模块、前级放大与滤波模块、检测线圈、锁相环同步检波模块、后级平滑滤波与放大模块、AD转换器、线圈驱动模块、单片机模块等部分组成。
💻 S
字号:
#include        "avrx.inc"
/*
        Copyright 1999-2001, Larry Barello
        larry@barello.net

REVISION HISTORY

20010403- Ported to avrx-ctoasm.inc

*/
        _MODULE(avrx_semaphores)

        _EXTERN(IntProlog)
        _EXTERN(RunQueue)
        _EXTERN(_QueuePid)
        _EXTERN(_Epilog)
        _EXTERN(Running)

        _CODESECTION

/*+
; --------------------------------------------------
; void AvrXWaitObjectSemaphore(pMutex)
; void AvrXWaitTimer:
; void AvrXWaitMessageAck:
; void AvrXWaitTask:
;
; Standard system objects have a semaphore as their
; second byte.  This call waits on that.
;
; PASSED:       p1h:p1l = Object
; RETURNS:      
; USES:         Z, X;       
; CALLS:
; ASSUMES:
; NOTES:        - 6/28/00 Changed code to only do IntProlog/Epilog
;               if Semaphore is _PEND or > _DONE
;               - Must stay critical through entire routine so we
;               don't "append" ourselves to a "DONE" semaphore
;               - Because of above, can assume the running code is
;               at the top of the run queue (change code later..)
;
;               Trivial case ~20 cycles
-*/
        _FUNCTION(AvrXWaitObjectSemaphore)
        _PUBLIC(AvrXWaitTimer)
        _PUBLIC(AvrXWaitMessageAck)
        _PUBLIC(AvrXWaitTask)
        
AvrXWaitTimer:
AvrXWaitMessageAck:
AvrXWaitTask:
AvrXWaitObjectSemaphore:
        subi    p1l, lo8(-2)
        sbci    p1h, hi8(-2)
        _ENDFUNC
/*+
; -----------------------------------------------
; void AvrXWaitSemaphore(pMutex)
;
; Tasks will queue up for a Semaphore, thus implementing 
; a Mutual Exclusion Semaphore.  For just plain old signaling
; only one task should wait on a semaphore.
;
; PASSED:       p1 =  Semaphore
; USES:         Z, tmp0, tmp1
; Returns:      void
; STACK:        One Context
;
; Notes:        Only called from user mode, may block.
-*/

        _FUNCTION(AvrXWaitSemaphore)

AvrXWaitSemaphore:
        mov     Zl, p1l
        mov     Zh, p1h

        BeginCritical           ; Must stay critical through entire routine

        ldd     tmp0, Z+NextL   ; Get semaphore
        ldd     tmp1, Z+NextH
        subi    tmp0, lo8(_DONE)
        sbci    tmp1, hi8(_DONE); Test trivial case of _DONE
        brne    aws01

        std     Z+NextL, tmp0   ; Reset Semaphore to _PEND
        std     Z+NextH, tmp1
        EndCriticalReturn       ; and return
aws01:
;        subi    tmp0, lo8(-_DONE)
;        sbci    tmp1, hi8(-_DONE); Restore semaphore

        rcall   IntProlog       ; Do task switch (ints disabled)

        ; With new code, we *can* assume we are at the top of the run queue
        
        lds     p2h, Running+NextH
        lds     p2l, Running+NextL
        ldi     Zl, lo8(RunQueue)
        ldi     Zh, hi8(RunQueue)
        rcall   _RemoveObject   ; Remove ourself from the run queue
        mov     Zl, p1l
        mov     Zh, p1h
        rcall   _AppendObject   ; Append ourselves to the Semaphore

        rjmp    _Epilog
        _ENDFUNC
/*+
; -----------------------------------------------
; void AvrXSetSemaphore(pMutex)
; void AvrXSetObjectSemaphore(pMythicalObject)
; void AvrXAckMessage(pMessageControlBlock)
;
; Sets (signals) an regular or object semaphore
;
; Signals a semaphore.  If semaphore is _PEND or _DONE, just mark
; DONE and return.  If a task is waiting, run it and set the semaphore 
; to the _PEND state.  
;
; Second Entry point is for Interrupt routines that want to Signal
; a semaphore.  Assumes context already saved.
;
; PASSED:       R25:R24 = Semaphore
; RETURNS:
; USES:         Everything
; CALLS:        AvrXIntSetSemaphore
; STACK:
; SIDE EFFECTS: 
-*/
        _FUNCTION(AvrXSetObjectSemaphore)
        _PUBLIC(AvrXAckMessage)

AvrXAckMessage:
AvrXSetObjectSemaphore:
        subi    p1l, lo8(-2)
        sbci    p1h, hi8(-2)
        _ENDFUNC
        
        _FUNCTION(AvrXSetSemaphore)
AvrXSetSemaphore:
        rcall   AvrXIntSetSemaphore
        tst     r1l
        breq    axss0
        ret
axss0:
        BeginCritical           ; Do task switch with interrupts off
        rcall   IntProlog
        EndCritical             ; Allow (any) pending interrupt to be serviced.
        rjmp    _Epilog
        
        _ENDFUNC
/*+
; -----------------------------------------------
; (void) AvrXIntSetSemaphore(pMutex)
; (void) AvrXIntSetObjectSemaphore(pMutex)
;
; Entry point for interrupt handlers (or code already switched into
; the system stack)
;
; PASSED:       p1h:p1l = Semaphore
; RETURNS:      r1l != 0, nothing queued
;                    = 0, task queued
; USES:         everything, 
; STACK:        2
; SIDE EFFECTS: Assumes p1l == r1l
; NOTES:        Doesn't accumulate sets.  If semaphore already set, the
;               just ignore it (not a counting semaphore)
-*/
        _FUNCTION(AvrXIntSetObjectSemaphore)
AvrXIntSetObjectSemaphore:      ; This one here because so small
        subi    p1l, lo8(-2)
        sbci    p1h, hi8(-2)
        _ENDFUNC

        _FUNCTION(AvrXIntSetSemaphore)
        
AvrXIntSetSemaphore:            ; Entry point for interrupt exit routines.
        mov     Zl, p1l
        mov     Zh, p1h
        ldi     p1l, lo8(_DONE)
        ldi     p1h, hi8(_DONE)

        BeginCritical

        ldd     p2h, Z+NextH
        ldd     p2l, Z+NextL
        cp      p1l, p2l 
        cpc     p1h, p2h        ; if 0x02 or higher...
        brlo    aiss00      
        std     Z+NextL, p1l    ; Trivial case of _PEND or _DONE
        std     Z+NextH, p1h    ; Set to _DONE
        ser     r1l
        EndCriticalReturn
        
aiss00:
        ldi     p1l, lo8(_LASTEV); Check for valid semaphore (e.g. >= $60)
;       ldi     p1h, hi8(_LASTEV); already zero...
        cp      p1l, p2l
        cpc     p1h, p2h
        brsh    BogusSemaphore

        rcall   _RemoveObjectAt ; Z->Prev, p2->Next (Object)
        
        EndCritical
        
        mov     p1l, p2l
        mov     p1h, p2h
        rcall   _QueuePid       ; p1h:p1l = Pid
        clr     r1l

BogusSemaphore:
        EndCriticalReturn
        _ENDFUNC
        
/*+-----------------------------------------------------------
        READ FUNCTION HEADERS AND CODE BEFORE USING!!! 
        
        _AppendObject
        _RemoveObject
        _RemoveFirstObject
        _RemoveObjectAt

        Have the following call/return conventions:

        Z = pointer to head of queue/removal point
        p2l:p2l = Pointer to Object Passed/Returned
        Z = pointer to next object on return.

        These functions are called by higher level AvrX functions
        that have the object pointer in P2, hence the use of P2 so
        calls can be made without shuffling data.
-*/
/*+
; -------------------------------------------------
; _AppendObject
;
; Appends an object to a queue
;
; PASSED:       Z = Queue head
;               p2h:p2l = Object
; RETURNS:
; USES:         Z, & Flags
; CALLS:
; ASSUMES:      Null terminated list; 
; NOTES:        
-*/
_ao00:
        mov     Zl, tmp0
        mov     Zh, tmp1
        _FUNCTION(_AppendObject)
_AppendObject:
        ldd     tmp0, Z+NextL
        ldd     tmp1, Z+NextH
        subi    tmp0, lo8(0)
        sbci    tmp1, hi8(0)    ; Zip to end of list
        brne    _ao00       
        
        std     Z+NextH, p2h
        std     Z+NextL, p2l   ; Prev->Next = Object
        mov     Zh, p2h
        mov     Zl, p2l
        std     Z+NextH, tmp1   ; Object->Next = 0
        std     Z+NextL, tmp0
        ret
        _ENDFUNC
/*+
; --------------------------------------------------
; _RemoveObject
;
; Removes an object from a queue.  Returns 0 if failed.
;
; PASSED:       Z         = Queue Head
;               p2h:p2l   = Object
; RETURNS:      p2h:p2l   = Object
;               tmp1:tmp0 = Object or 0
;               Z         = Next object in list
;               Z Flag set if Failed
;               Z Flag cleared if success
;
; USES:         Z, Flags
; CALLS:
; ASSUMES:      Called within a critical section
; NOTES:        Z are side effects used else where in AvrX
-*/
_ro00:
        mov     Zh, tmp1
        mov     Zl, tmp0
        _FUNCTION(_RemoveObject)
_RemoveObject:
        ldd     tmp0, Z+NextL
        ldd     tmp1, Z+NextH
        cp      p2l, tmp0
        cpc     p2h, tmp1
        breq    _RemoveObjectAt ; Match, we got it.
        subi    tmp0, lo8(0)
        sbci    tmp1, hi8(0)    ; Test end of list
        brne    _ro00           ; Walk the list
        ret                     ; End of list
        _ENDFUNC
        
/*+
; --------------------------------------------------
; pQueue _RemoveFirstObject(pQueue)
;
; Removes the first item in a queue. Return Zero if empty.
;
; PASSED:       Z       = Queue head
; RETURNS:      p2h:p2l = 0 if list empty, otherwize
;               Z       = Next Item
;               Zero Flag set if P2 == 0
;               Zero flag cleared if P2 != 0
;
; USES:         Flags
; CALLS:
; ASSUMES:      Null terminated list
; NOTES:        Interrupts NOT disabled.  Must disable if possibility
;               of something being insterted at head of queue
-*/
        _FUNCTION(_RemoveFirstObject)
_RemoveFirstObject:
        ldd     p2l, Z+NextL
        ldd     p2h, Z+NextH     ; X = pointer to object
        subi    p2l, lo8(0)
        sbci    p2h, hi8(0)      ; Test end of list
        brne    _RemoveObjectAt
        ret
        _ENDFUNC
        
/*+
; --------------------------------------------------
; pQueue _RemoveObjectAt(pQueue)
;
; Removes the  item in a queue. 
;
; PASSED:       Z       = Prev
;               p2h:p2l = Object
;
; RETURNS:      p2h:p2l = Object
;               Z       = Next Item
;               Zero flag cleared
;
; USES:         Flags, tmp0-2
; CALLS:
; ASSUMES:      Null terminated list, valid object pointer
; NOTES:        Interrupts NOT disabled.  Must disable if possibility
;               of something being insterted at head of queue
-*/
        _FUNCTION(_RemoveObjectAt)

_RemoveObjectAt:                ; Z = Prev, p2 = Object
        mov     tmp2, Yl
        mov     tmp3, Yh
        mov     Yl, p2l
        mov     Yh, p2h
        
        ldd     p2h, Y+NextH
        ldd     p2l, Y+NextL
        std     Z+NextH, p2h
        std     Z+NextL, p2l    ; Prev->Next = Object->Next
        mov     Zl, p2l         ; Return Next in Z
        mov     Zh, p2h
        clr     p2l
        std     Y+NextL, p2l    ; Object->Next = 0
        std     Y+NextH, p2l

        mov     p2h, Yh         ; restore p2 & Y
        mov     p2l, Yl
        mov     Yl, tmp2
        mov     Yh, tmp3
        clz                     ; Return non-zero
        ret
        
        _ENDFUNC
        _END

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -