📄 os_sem.s43
字号:
NAME os_sem(16)
RSEG CODE(1)
EXTERN OSEventFreeList
EXTERN OSIntNesting
PUBLIC OSSemAccept
PUBLIC OSSemCreate
PUBLIC OSSemDel
PUBLIC OSSemPend
PUBLIC OSSemPost
PUBLIC OSSemQuery
EXTERN OSTCBCur
EXTERN OS_EventTO
EXTERN OS_EventTaskRdy
EXTERN OS_EventTaskWait
EXTERN OS_EventWaitListInit
EXTERN OS_Sched
EXTERN ?CL430_1_26_L08
RSEG CODE
OSSemAccept:
; 1. /*
; 2. *********************************************************************************************************
; 3. * uC/OS-II
; 4. * The Real-Time Kernel
; 5. * SEMAPHORE MANAGEMENT
; 6. *
; 7. * (c) Copyright 1992-2002, Jean J. Labrosse, Weston, FL
; 8. * All Rights Reserved
; 9. *
; 10. * File : OS_SEM.C
; 11. * By : Jean J. Labrosse
; 12. *********************************************************************************************************
; 13. */
; 14.
; 15. #ifndef OS_MASTER_FILE
; 16. #include "includes.h"
; 17. #endif
; 18.
; 19. #if OS_SEM_EN > 0
; 20. /*
; 21. *********************************************************************************************************
; 22. * ACCEPT SEMAPHORE
; 23. *
; 24. * Description: This function checks the semaphore to see if a resource is available or, if an event
; 25. * occurred. Unlike OSSemPend(), OSSemAccept() does not suspend the calling task if the
; 26. * resource is not available or the event did not occur.
; 27. *
; 28. * Arguments : pevent is a pointer to the event control block
; 29. *
; 30. * Returns : > 0 if the resource is available or the event did not occur the semaphore is
; 31. * decremented to obtain the resource.
; 32. * == 0 if the resource is not available or the event did not occur or,
; 33. * if 'pevent' is a NULL pointer or,
; 34. * if you didn't pass a pointer to a semaphore
; 35. *********************************************************************************************************
; 36. */
; 37.
; 38. #if OS_SEM_ACCEPT_EN > 0
; 39. INT16U OSSemAccept (OS_EVENT *pevent)
; 40. {
; 41. #if OS_CRITICAL_METHOD == 3 /* Allocate storage for CPU status register */
; 42. OS_CPU_SR cpu_sr;
; 43. #endif
; 44. INT16U cnt;
; 45.
; 46.
; 47. #if OS_ARG_CHK_EN > 0
; 48. if (pevent == (OS_EVENT *)0) { /* Validate 'pevent' */
CMP #0,R12
JNE (?0057)
; 49. return (0);
; 50. }
RET
?0057:
; 51. if (pevent->OSEventType != OS_EVENT_TYPE_SEM) { /* Validate event block type */
MOV.B #3,R13
CMP.B @R12,R13
JEQ (?0059)
; 52. return (0);
MOV #0,R12
; 53. }
RET
?0059:
; 54. #endif
; 55. OS_ENTER_CRITICAL();
DINT
; 56. cnt = pevent->OSEventCnt;
MOV 2(R12),R13
; 57. if (cnt > 0) { /* See if resource is available */
CMP #0,R13
JEQ (?0061)
; 58. pevent->OSEventCnt--; /* Yes, decrement semaphore and notify caller */
ADD #-1,2(R12)
?0061:
; 59. }
; 60. OS_EXIT_CRITICAL();
EINT
; 61. return (cnt); /* Return semaphore count */
MOV R13,R12
; 62. }
RET
OSSemCreate:
; 63. #endif
; 64.
; 65. /*$PAGE*/
; 66. /*
; 67. *********************************************************************************************************
; 68. * CREATE A SEMAPHORE
; 69. *
; 70. * Description: This function creates a semaphore.
; 71. *
; 72. * Arguments : cnt is the initial value for the semaphore. If the value is 0, no resource is
; 73. * available (or no event has occurred). You initialize the semaphore to a
; 74. * non-zero value to specify how many resources are available (e.g. if you have
; 75. * 10 resources, you would initialize the semaphore to 10).
; 76. *
; 77. * Returns : != (void *)0 is a pointer to the event control clock (OS_EVENT) associated with the
; 78. * created semaphore
; 79. * == (void *)0 if no event control blocks were available
; 80. *********************************************************************************************************
; 81. */
; 82.
; 83. OS_EVENT *OSSemCreate (INT16U cnt)
; 84. {
PUSH R10
; 85. #if OS_CRITICAL_METHOD == 3 /* Allocate storage for CPU status register */
; 86. OS_CPU_SR cpu_sr;
; 87. #endif
; 88. OS_EVENT *pevent;
; 89.
; 90.
; 91. if (OSIntNesting > 0) { /* See if called from ISR ... */
CMP.B #0,&OSIntNesting
JEQ (?0064)
; 92. return ((OS_EVENT *)0); /* ... can't CREATE from an ISR */
MOV #0,R12
; 93. }
JMP (?0069)
?0064:
; 94. OS_ENTER_CRITICAL();
DINT
; 95. pevent = OSEventFreeList; /* Get next free event control block */
MOV &OSEventFreeList,R10
; 96. if (OSEventFreeList != (OS_EVENT *)0) { /* See if pool of free ECB pool was empty */
CMP #0,&OSEventFreeList
JEQ (?0066)
; 97. OSEventFreeList = (OS_EVENT *)OSEventFreeList->OSEventPtr;
MOV &OSEventFreeList,R13
MOV 4(R13),&OSEventFreeList
?0066:
; 98. }
; 99. OS_EXIT_CRITICAL();
EINT
; 100. if (pevent != (OS_EVENT *)0) { /* Get an event control block */
CMP #0,R10
JEQ (?0068)
; 101. pevent->OSEventType = OS_EVENT_TYPE_SEM;
MOV.B #3,0(R10)
; 102. pevent->OSEventCnt = cnt; /* Set semaphore value */
MOV R12,2(R10)
; 103. pevent->OSEventPtr = (void *)0; /* Unlink from ECB free list */
MOV #0,4(R10)
; 104. OS_EventWaitListInit(pevent); /* Initialize to 'nobody waiting' on sem. */
MOV R10,R12
CALL #OS_EventWaitListInit
?0068:
; 105. }
; 106. return (pevent);
MOV R10,R12
; 107. }
?0069:
POP R10
RET
OSSemDel:
; 108.
; 109. /*$PAGE*/
; 110. /*
; 111. *********************************************************************************************************
; 112. * DELETE A SEMAPHORE
; 113. *
; 114. * Description: This function deletes a semaphore and readies all tasks pending on the semaphore.
; 115. *
; 116. * Arguments : pevent is a pointer to the event control block associated with the desired
; 117. * semaphore.
; 118. *
; 119. * opt determines delete options as follows:
; 120. * opt == OS_DEL_NO_PEND Delete semaphore ONLY if no task pending
; 121. * opt == OS_DEL_ALWAYS Deletes the semaphore even if tasks are waiting.
; 122. * In this case, all the tasks pending will be readied.
; 123. *
; 124. * err is a pointer to an error code that can contain one of the following values:
; 125. * OS_NO_ERR The call was successful and the semaphore was deleted
; 126. * OS_ERR_DEL_ISR If you attempted to delete the semaphore from an ISR
; 127. * OS_ERR_INVALID_OPT An invalid option was specified
; 128. * OS_ERR_TASK_WAITING One or more tasks were waiting on the semaphore
; 129. * OS_ERR_EVENT_TYPE If you didn't pass a pointer to a semaphore
; 130. * OS_ERR_PEVENT_NULL If 'pevent' is a NULL pointer.
; 131. *
; 132. * Returns : pevent upon error
; 133. * (OS_EVENT *)0 if the semaphore was successfully deleted.
; 134. *
; 135. * Note(s) : 1) This function must be used with care. Tasks that would normally expect the presence of
; 136. * the semaphore MUST check the return code of OSSemPend().
; 137. * 2) OSSemAccept() callers will not know that the intended semaphore has been deleted unless
; 138. * they check 'pevent' to see that it's a NULL pointer.
; 139. * 3) This call can potentially disable interrupts for a long time. The interrupt disable
; 140. * time is directly proportional to the number of tasks waiting on the semaphore.
; 141. * 4) Because ALL tasks pending on the semaphore will be readied, you MUST be careful in
; 142. * applications where the semaphore is used for mutual exclusion because the resource(s)
; 143. * will no longer be guarded by the semaphore.
; 144. *********************************************************************************************************
; 145. */
; 146.
; 147. #if OS_SEM_DEL_EN > 0
; 148. OS_EVENT *OSSemDel (OS_EVENT *pevent, INT8U opt, INT8U *err)
; 149. {
PUSH R10
PUSH R11
PUSH R8
MOV R12,R11
MOV 8(SP),R8
; 150. #if OS_CRITICAL_METHOD == 3 /* Allocate storage for CPU status register */
; 151. OS_CPU_SR cpu_sr;
; 152. #endif
; 153. BOOLEAN tasks_waiting;
; 154.
; 155.
; 156. if (OSIntNesting > 0) { /* See if called from ISR ... */
CMP.B #0,&OSIntNesting
JEQ (?0071)
; 157. *err = OS_ERR_DEL_ISR; /* ... can't DELETE from an ISR */
MOV.B #140,0(R8)
; 158. return (pevent);
MOV R11,R12
; 159. }
JMP (?0090)
?0071:
; 160. #if OS_ARG_CHK_EN > 0
; 161. if (pevent == (OS_EVENT *)0) { /* Validate 'pevent' */
CMP #0,R11
JNE (?0073)
; 162. *err = OS_ERR_PEVENT_NULL;
MOV.B #4,0(R8)
; 163. return (pevent);
MOV #0,R12
; 164. }
JMP (?0090)
?0073:
; 165. if (pevent->OSEventType != OS_EVENT_TYPE_SEM) { /* Validate event block type */
MOV.B #3,R12
CMP.B @R11,R12
JEQ (?0075)
; 166. *err = OS_ERR_EVENT_TYPE;
MOV.B #1,0(R8)
; 167. return (pevent);
MOV R11,R12
; 168. }
JMP (?0090)
?0075:
; 169. #endif
; 170. OS_ENTER_CRITICAL();
DINT
; 171. if (pevent->OSEventGrp != 0x00) { /* See if any tasks waiting on semaphore */
CMP.B #0,1(R11)
JEQ (?0077)
; 172. tasks_waiting = TRUE; /* Yes */
MOV.B #1,R10
; 173. } else {
JMP (?0078)
?0077:
; 174. tasks_waiting = FALSE; /* No */
MOV.B #0,R10
?0078:
; 175. }
; 176. switch (opt) {
SUB.B #0,R14
JEQ (?0080)
SUB.B #1,R14
JEQ (?0083)
JMP (?0089)
?0080:
; 177. case OS_DEL_NO_PEND: /* Delete semaphore only if no task waiting */
; 178. if (tasks_waiting == FALSE) {
CMP.B #0,R10
JNE (?0082)
; 179. pevent->OSEventType = OS_EVENT_TYPE_UNUSED;
MOV.B #0,0(R11)
; 180. pevent->OSEventPtr = OSEventFreeList; /* Return Event Control Block to free list */
MOV &OSEventFreeList,4(R11)
; 181. OSEventFreeList = pevent; /* Get next free event control block */
MOV R11,&OSEventFreeList
; 182. OS_EXIT_CRITICAL();
EINT
; 183. *err = OS_NO_ERR;
MOV.B #0,0(R8)
; 184. return ((OS_EVENT *)0); /* Semaphore has been deleted */
MOV #0,R12
; 185. } else {
JMP (?0090)
?0082:
; 186. OS_EXIT_CRITICAL();
EINT
; 187. *err = OS_ERR_TASK_WAITING;
MOV.B #8,0(R8)
; 188. return (pevent);
MOV R11,R12
; 189. }
JMP (?0090)
?0083:
; 190.
; 191. case OS_DEL_ALWAYS: /* Always delete the semaphore */
; 192. while (pevent->OSEventGrp != 0x00) { /* Ready ALL tasks waiting for semaphore */
CMP.B #0,1(R11)
JEQ (?0084)
; 193. OS_EventTaskRdy(pevent, (void *)0, OS_STAT_SEM);
PUSH.B #1
MOV #0,R14
MOV R11,R12
CALL #OS_EventTaskRdy
ADD #2,SP
JMP (?0083)
?0084:
; 194. }
; 195. pevent->OSEventType = OS_EVENT_TYPE_UNUSED;
MOV.B #0,0(R11)
; 196. pevent->OSEventPtr = OSEventFreeList; /* Return Event Control Block to free list */
MOV &OSEventFreeList,4(R11)
; 197. OSEventFreeList = pevent; /* Get next free event control block */
MOV R11,&OSEventFreeList
; 198. OS_EXIT_CRITICAL();
EINT
; 199. if (tasks_waiting == TRUE) { /* Reschedule only if task(s) were waiting */
CMP.B #1,R10
JNE (?0088)
; 200. OS_Sched(); /* Find highest priority task ready to run */
CALL #OS_Sched
?0088:
; 201. }
; 202. *err = OS_NO_ERR;
MOV.B #0,0(R8)
; 203. return ((OS_EVENT *)0); /* Semaphore has been deleted */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -