📄 os_sem.s
字号:
.module OS_SEM.c
.area text(rom, con, rel)
.dbfile F:\AVRPRA~1\ucosii-port2-mega8\OS_SEM.c
.dbfunc e OSSemAccept _OSSemAccept fi
.dbstruct 0 9 .1
.dbfield 0 OSEventType c
.dbfield 1 OSEventGrp c
.dbfield 2 OSEventCnt i
.dbfield 4 OSEventPtr pV
.dbfield 6 OSEventTbl A[3:3]c
.dbend
; cpu_sr -> R22
; cnt -> R20,R21
; pevent -> R10,R11
.even
_OSSemAccept::
rcall push_gset3
movw R10,R16
.dbline -1
.dbline 40
; /*
; *********************************************************************************************************
; * uC/OS-II
; * The Real-Time Kernel
; * SEMAPHORE MANAGEMENT
; *
; * (c) Copyright 1992-2001, Jean J. Labrosse, Weston, FL
; * All Rights Reserved
; *
; * File : OS_SEM.C
; * By : Jean J. Labrosse
; *********************************************************************************************************
; */
;
; #ifndef OS_MASTER_FILE
; #include "includes.h"
; #endif
;
; #if OS_SEM_EN > 0
; /*
; *********************************************************************************************************
; * ACCEPT SEMAPHORE
; *
; * Description: This function checks the semaphore to see if a resource is available or, if an event
; * occurred. Unlike OSSemPend(), OSSemAccept() does not suspend the calling task if the
; * resource is not available or the event did not occur.
; *
; * Arguments : pevent is a pointer to the event control block
; *
; * Returns : > 0 if the resource is available or the event did not occur the semaphore is
; * decremented to obtain the resource.
; * == 0 if the resource is not available or the event did not occur or,
; * if 'pevent' is a NULL pointer or,
; * if you didn't pass a pointer to a semaphore
; *********************************************************************************************************
; */
;
; #if OS_SEM_ACCEPT_EN > 0
; INT16U OSSemAccept (OS_EVENT *pevent)
; {
.dbline 55
; #if OS_CRITICAL_METHOD == 3 /* Allocate storage for CPU status register */
; OS_CPU_SR cpu_sr;
; #endif
; INT16U cnt;
;
;
; #if OS_ARG_CHK_EN > 0
; if (pevent == (OS_EVENT *)0) { /* Validate 'pevent' */
; return (0);
; }
; if (pevent->OSEventType != OS_EVENT_TYPE_SEM) { /* Validate event block type */
; return (0);
; }
; #endif
; OS_ENTER_CRITICAL();
rcall _OS_CPU_SR_Save
mov R22,R16
.dbline 56
; cnt = pevent->OSEventCnt;
movw R30,R10
ldd R20,z+2
ldd R21,z+3
.dbline 57
; if (cnt > 0) { /* See if resource is available */
cpi R20,0
cpc R20,R21
breq L4
X0:
.dbline 57
.dbline 58
; pevent->OSEventCnt--; /* Yes, decrement semaphore and notify caller */
movw R24,R10
adiw R24,2
movw R30,R24
ldd R24,z+0
ldd R25,z+1
sbiw R24,1
std z+1,R25
std z+0,R24
.dbline 59
; }
L4:
.dbline 60
; OS_EXIT_CRITICAL();
mov R16,R22
rcall _OS_CPU_SR_Restore
.dbline 61
; return (cnt); /* Return semaphore count */
movw R16,R20
.dbline -2
L3:
rcall pop_gset3
.dbline 0 ; func end
ret
.dbsym r cpu_sr 22 c
.dbsym r cnt 20 i
.dbsym r pevent 10 pS[.1]
.dbend
.dbfunc e OSSemCreate _OSSemCreate fpS[.1]
; cpu_sr -> R10
; pevent -> R20,R21
; cnt -> R22,R23
.even
_OSSemCreate::
rcall push_gset3
movw R22,R16
.dbline -1
.dbline 84
; }
; #endif
;
; /*$PAGE*/
; /*
; *********************************************************************************************************
; * CREATE A SEMAPHORE
; *
; * Description: This function creates a semaphore.
; *
; * Arguments : cnt is the initial value for the semaphore. If the value is 0, no resource is
; * available (or no event has occurred). You initialize the semaphore to a
; * non-zero value to specify how many resources are available (e.g. if you have
; * 10 resources, you would initialize the semaphore to 10).
; *
; * Returns : != (void *)0 is a pointer to the event control clock (OS_EVENT) associated with the
; * created semaphore
; * == (void *)0 if no event control blocks were available
; *********************************************************************************************************
; */
;
; OS_EVENT *OSSemCreate (INT16U cnt)
; {
.dbline 91
; #if OS_CRITICAL_METHOD == 3 /* Allocate storage for CPU status register */
; OS_CPU_SR cpu_sr;
; #endif
; OS_EVENT *pevent;
;
;
; if (OSIntNesting > 0) { /* See if called from ISR ... */
clr R2
lds R3,_OSIntNesting
cp R2,R3
brsh L7
.dbline 91
.dbline 92
; return ((OS_EVENT *)0); /* ... can't CREATE from an ISR */
clr R16
clr R17
rjmp L6
L7:
.dbline 94
; }
; OS_ENTER_CRITICAL();
rcall _OS_CPU_SR_Save
mov R10,R16
.dbline 95
; pevent = OSEventFreeList; /* Get next free event control block */
lds R20,_OSEventFreeList
lds R21,_OSEventFreeList+1
.dbline 96
; if (OSEventFreeList != (OS_EVENT *)0) { /* See if pool of free ECB pool was empty */
cpi R20,0
cpc R20,R21
breq L9
X1:
.dbline 96
.dbline 97
; OSEventFreeList = (OS_EVENT *)OSEventFreeList->OSEventPtr;
lds R30,_OSEventFreeList
lds R31,_OSEventFreeList+1
ldd R2,z+4
ldd R3,z+5
sts _OSEventFreeList+1,R3
sts _OSEventFreeList,R2
.dbline 98
; }
L9:
.dbline 99
; OS_EXIT_CRITICAL();
mov R16,R10
rcall _OS_CPU_SR_Restore
.dbline 100
; if (pevent != (OS_EVENT *)0) { /* Get an event control block */
cpi R20,0
cpc R20,R21
breq L11
X2:
.dbline 100
.dbline 101
; pevent->OSEventType = OS_EVENT_TYPE_SEM;
ldi R24,3
movw R30,R20
std z+0,R24
.dbline 102
; pevent->OSEventCnt = cnt; /* Set semaphore value */
std z+3,R23
std z+2,R22
.dbline 103
; OS_EventWaitListInit(pevent);
movw R16,R20
rcall _OS_EventWaitListInit
.dbline 104
; }
L11:
.dbline 105
; return (pevent);
movw R16,R20
.dbline -2
L6:
rcall pop_gset3
.dbline 0 ; func end
ret
.dbsym r cpu_sr 10 c
.dbsym r pevent 20 pS[.1]
.dbsym r cnt 22 i
.dbend
.dbfunc e OSSemDel _OSSemDel fpS[.1]
; tasks_waiting -> R12
; cpu_sr -> R10
; err -> R22,R23
; opt -> R14
; pevent -> R20,R21
.even
_OSSemDel::
rcall push_gset5
mov R14,R18
movw R20,R16
sbiw R28,1
ldd R22,y+11
ldd R23,y+12
.dbline -1
.dbline 148
; }
;
; /*$PAGE*/
; /*
; *********************************************************************************************************
; * DELETE A SEMAPHORE
; *
; * Description: This function deletes a semaphore and readies all tasks pending on the semaphore.
; *
; * Arguments : pevent is a pointer to the event control block associated with the desired
; * semaphore.
; *
; * opt determines delete options as follows:
; * opt == OS_DEL_NO_PEND Delete semaphore ONLY if no task pending
; * opt == OS_DEL_ALWAYS Deletes the semaphore even if tasks are waiting.
; * In this case, all the tasks pending will be readied.
; *
; * err is a pointer to an error code that can contain one of the following values:
; * OS_NO_ERR The call was successful and the semaphore was deleted
; * OS_ERR_DEL_ISR If you attempted to delete the semaphore from an ISR
; * OS_ERR_INVALID_OPT An invalid option was specified
; * OS_ERR_TASK_WAITING One or more tasks were waiting on the semaphore
; * OS_ERR_EVENT_TYPE If you didn't pass a pointer to a semaphore
; * OS_ERR_PEVENT_NULL If 'pevent' is a NULL pointer.
; *
; * Returns : pevent upon error
; * (OS_EVENT *)0 if the semaphore was successfully deleted.
; *
; * Note(s) : 1) This function must be used with care. Tasks that would normally expect the presence of
; * the semaphore MUST check the return code of OSSemPend().
; * 2) OSSemAccept() callers will not know that the intended semaphore has been deleted unless
; * they check 'pevent' to see that it's a NULL pointer.
; * 3) This call can potentially disable interrupts for a long time. The interrupt disable
; * time is directly proportional to the number of tasks waiting on the semaphore.
; * 4) Because ALL tasks pending on the semaphore will be readied, you MUST be careful in
; * applications where the semaphore is used for mutual exclusion because the resource(s)
; * will no longer be guarded by the semaphore.
; *********************************************************************************************************
; */
;
; #if OS_SEM_DEL_EN > 0
; OS_EVENT *OSSemDel (OS_EVENT *pevent, INT8U opt, INT8U *err)
; {
.dbline 155
; #if OS_CRITICAL_METHOD == 3 /* Allocate storage for CPU status register */
; OS_CPU_SR cpu_sr;
; #endif
; BOOLEAN tasks_waiting;
;
;
; if (OSIntNesting > 0) { /* See if called from ISR ... */
clr R2
lds R3,_OSIntNesting
cp R2,R3
brsh L14
.dbline 155
.dbline 156
; *err = OS_ERR_DEL_ISR; /* ... can't DELETE from an ISR */
ldi R24,140
movw R30,R22
std z+0,R24
.dbline 157
; return (pevent);
movw R16,R20
rjmp L13
L14:
.dbline 169
; }
; #if OS_ARG_CHK_EN > 0
; if (pevent == (OS_EVENT *)0) { /* Validate 'pevent' */
; *err = OS_ERR_PEVENT_NULL;
; return (pevent);
; }
; if (pevent->OSEventType != OS_EVENT_TYPE_SEM) { /* Validate event block type */
; *err = OS_ERR_EVENT_TYPE;
; return (pevent);
; }
; #endif
; OS_ENTER_CRITICAL();
rcall _OS_CPU_SR_Save
mov R10,R16
.dbline 170
; if (pevent->OSEventGrp != 0x00) { /* See if any tasks waiting on semaphore */
movw R30,R20
ldd R2,z+1
tst R2
breq L16
.dbline 170
.dbline 171
; tasks_waiting = TRUE; /* Yes */
clr R12
inc R12
.dbline 172
rjmp L17
L16:
.dbline 172
; } else {
.dbline 173
; tasks_waiting = FALSE; /* No */
clr R12
.dbline 174
; }
L17:
.dbline 175
clr R15
tst R14
brne X3
tst R15
breq L21
X3:
movw R24,R14
cpi R24,1
ldi R30,0
cpc R25,R30
brne X5
rjmp L26
X5:
rjmp L18
X4:
.dbline 175
; switch (opt) {
L21:
.dbline 177
; case OS_DEL_NO_PEND: /* Delete semaphore only if no task waiting */
; if (tasks_waiting == FALSE) {
tst R12
brne L22
.dbline 177
.dbline 178
; pevent->OSEventType = OS_EVENT_TYPE_UNUSED;
clr R2
movw R30,R20
std z+0,R2
.dbline 179
; pevent->OSEventPtr = OSEventFreeList; /* Return Event Control Block to free list */
lds R2,_OSEventFreeList
lds R3,_OSEventFreeList+1
std z+5,R3
std z+4,R2
.dbline 180
; OSEventFreeList = pevent; /* Get next free event control block */
sts _OSEventFreeList+1,R21
sts _OSEventFreeList,R20
.dbline 181
; OS_EXIT_CRITICAL();
mov R16,R10
rcall _OS_CPU_SR_Restore
.dbline 182
; *err = OS_NO_ERR;
clr R2
movw R30,R22
std z+0,R2
.dbline 183
; return ((OS_EVENT *)0); /* Semaphore has been deleted */
clr R16
clr R17
rjmp L13
L22:
.dbline 184
; } else {
.dbline 185
; OS_EXIT_CRITICAL();
mov R16,R10
rcall _OS_CPU_SR_Restore
.dbline 186
; *err = OS_ERR_TASK_WAITING;
ldi R24,8
movw R30,R22
std z+0,R24
.dbline 187
; return (pevent);
movw R16,R20
rjmp L13
L25:
.dbline 191
.dbline 192
ldi R24,1
std y+0,R24
clr R18
clr R19
movw R16,R20
rcall _OS_EventTaskRdy
.dbline 193
L26:
.dbline 191
; }
;
; case OS_DEL_ALWAYS: /* Always delete the semaphore */
; while (pevent->OSEventGrp != 0x00) { /* Ready ALL tasks waiting for semaphore */
movw R30,R20
ldd R2,z+1
tst R2
brne L25
.dbline 194
; OS_EventTaskRdy(pevent, (void *)0, OS_STAT_SEM);
; }
; pevent->OSEventType = OS_EVENT_TYPE_UNUSED;
clr R2
movw R30,R20
std z+0,R2
.dbline 195
; pevent->OSEventPtr = OSEventFreeList; /* Return Event Control Block to free list */
lds R2,_OSEventFreeList
lds R3,_OSEventFreeList+1
std z+5,R3
std z+4,R2
.dbline 196
; OSEventFreeList = pevent; /* Get next free event control block */
sts _OSEventFreeList+1,R21
sts _OSEventFreeList,R20
.dbline 197
; OS_EXIT_CRITICAL();
mov R16,R10
rcall _OS_CPU_SR_Restore
.dbline 198
; if (tasks_waiting == TRUE) { /* Reschedule only if task(s) were waiting */
mov R24,R12
cpi R24,1
brne L28
.dbline 198
.dbline 199
; OS_Sched(); /* Find highest priority task ready to run */
rcall _OS_Sched
.dbline 200
; }
L28:
.dbline 201
; *err = OS_NO_ERR;
clr R2
movw R30,R22
std z+0,R2
.dbline 202
; return ((OS_EVENT *)0); /* Semaphore has been deleted */
clr R16
clr R17
rjmp L13
L18:
.dbline 205
;
; default:
; OS_EXIT_CRITICAL();
mov R16,R10
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -