OS_TIME.C

简介: 1 /*2 *************************************************************************************************3 * uC/OS-II实时控制内核4 *
1 /*
2 *************************************************************************************************
3 *                                        uC/OS-II实时控制内核
4 *                                            主要的包含文件
5 *                                             时钟管理项
6 * 文 件: OS_TIME.C      时钟管理代码
7 * 作 者: Jean J. Labrosse
8 * 中文注解: 钟常慰  zhongcw @ 126.com 整理:lin-credible 译注版本:1.0 请尊重原版内容
9 *********************************************************************************************************
10 */
11
12 #ifndef  OS_MASTER_FILE            //是否已定义OS_MASTER_FILE主文件
13 #include "includes.h"              //包含"includes.h"文件,部分C语言头文件的汇总打包文件
14 #endif                             //定义结束
15
16 /*
17 *********************************************************************************************************
18 *                  将一个任务延时若干个时钟节拍(DELAY TASK 'n' TICKS (n from 0 to 65535))
19 *
20 * 描述: 将一个任务延时若干个时钟节拍。如果延时时间大于0, 系统将立即进行任务调度. 延时时间的长度
21 *       可从0到65535个时钟节拍。延时时间0表示不进行延时,函数将立即返回调用者。延时的具体时间依
22 *       赖于系统每秒钟有多少时钟节拍(由文件SO_CFG.H中的常量OS_TICKS_PER_SEC设定)。
23 *
24 * 附加:调用该函数会使uC/OS-ii进行一次任务调度,并且执行下一个优先级最高的就绪态任务。任务调用
25 *       OSTimeDly()后,一旦规定的时间期满或者有其它的任务通过调用OSTimeDlyResume()取消了延时,
26 *       它就会马上进入就绪状态。注意,只有当该任务在所有就绪任务中具有最高的优先级时,它才会立即
27 *       运行。
28 * 参数: ticks  为要延时的时钟节拍数。(一个1 到65535之间的数)
29 *
30 * 返回: 无
31 * 注意: 注意到延时时间0表示不进行延时操作,而立即返回调用者. 为了确保设定的延时时间,建议用户设定
32 *       的时钟节拍数加1。例如,希望延时10个时钟节拍,可设定参数为11。
33 *********************************************************************************************************
34 */
35 void  OSTimeDly (INT16U ticks)       //任务延时函数(时钟节拍数)
36 {
37 #if OS_CRITICAL_METHOD == 3          //中断函数被设定为模式3
38     OS_CPU_SR  cpu_sr;
39 #endif
40
41
42     if (ticks > 0) {                 //如果延时设定为0值,表示不想对任务延时,返回调用任务
43         OS_ENTER_CRITICAL();         //关闭中断
44         if ((OSRdyTbl[OSTCBCur->OSTCBY] &= ~OSTCBCur->OSTCBBitX) == 0) {
45             OSRdyGrp &= ~OSTCBCur->OSTCBBitY;
46         }
47                                      //非0值会使得任务延时函数OSTimeDly()将当前任务从就绪表中移除
48         OSTCBCur->OSTCBDly = ticks;  //接着,这个延时节拍数会被保存在当前任务的OS_TCB中
49         OS_EXIT_CRITICAL();          //打开中断
50         OS_Sched();                  //既然任务已经不再处于就绪状态,(任务调度)
51                                      //任务调度程序会执行下一个优先级最高的就绪任务。
52     }
53 }
54 /*$PAGE*/
55 /*
56 *********************************************************************************************************
57 *                    将一个任务延时若干时间(DELAY TASK FOR SPECIFIED TIME)
58 *
59 * 描述: 将一个任务延时若干时间。延时的单位是小时、分、秒、毫秒。所以使用OSTimeDlyHMSM()比OSTimeDly()
60 *       更方便。调用OSTimeDlyHMSM()后,如果延时时间不为0,系统将立即进行任务调度。
61 *
62 * 参数: hours     为延时小时数,范围从0-255. (max. is 255)
63 *       minutes   为延时分钟数,范围从0-59.  (max. 59)
64 *       seconds   为延时秒数,范围从0-59.    (max. 59)
65 *       milli     为延时毫秒数,范围从0-999. (max. 999)
66 *       需要说明的是,延时操作函数都是以时钟节拍为为单位的。实际的延时时间是时钟节拍的整数倍。例如系统
67 *       每次时钟节拍间隔是10ms,如果设定延时为5ms,将不产生任何延时操作,而设定延时15ms,实际的延时是
68 *       两个时钟节拍,也就是20ms。
69 *
70 * 附加:调用OSTimeDlyHMSM()函数也会使uC/OS-ii进行一次任务调度,并且执行下一个优先级最高的就绪态任务。
71 *       任务调用OSTimeDlyHMSM()后,一旦规定的时间期满或者有其它的任务通过调用OSTimeDlyResume()取消了延
72 *       时(恢复延时的任务OSTimeDlyResume()),它就会马上处于就绪态。同样,只有当该任务在所有就绪态任务
73 *       中具有最高的优先级时,它才会立即运行。
74 *
75 * 返回: OS_NO_ERR                 函数调用成功;
76 *       OS_TIME_INVALID_MINUTES   参数错误,分钟数大于59;
77 *       OS_TIME_INVALID_SECONDS   参数错误,秒数大于59;
78 *       OS_TIME_INVALID_MS        参数错误,毫秒数大于999;
79 *       OS_TIME_ZERO_DLY          四个参数全为0.
80 *
81 * 注意: OSTimeDlyHMSM(0,0,0,0)表示不进行延时操作, 而立即返回调用者. 另外, 如果延时总时间超过65535个
82 *       时钟节拍,将不能用OSTimeDlyResume()函数终止延时并唤醒任务。
83 *********************************************************************************************************
84 */
85
86 #if OS_TIME_DLY_HMSM_EN > 0         //允许生成OSTimeDlyHMSM() 函数代码
87 INT8U  OSTimeDlyHMSM (INT8U hours, INT8U minutes, INT8U seconds, INT16U milli)
88 {                                   //将一个任务延时若干时间(设定时、分、秒、毫秒)
89     INT32U ticks;                   //定义节拍数
90     INT16U loops;                   //定义循环次数
91                                     //当设定值大于0值(是否时有效值)
92     if (hours > 0 || minutes > 0 || seconds > 0 || milli > 0) {
93         if (minutes > 59) {         //如果分钟>59,则返回参数错误,分钟数大于59;
94             return (OS_TIME_INVALID_MINUTES);
95         }
96         if (seconds > 59) {         //如果秒>59,则返回参数错误,秒数大于59;
97             return (OS_TIME_INVALID_SECONDS);
98         }
99         if (milli > 999) {          //如果毫秒>999,则返回参数错误,毫秒数大于999;
100             return (OS_TIME_INVALID_MILLI);
101         }
102 /*
103 *   因为uC/OS-ii只知道节拍,所以节拍总数是从指定的时间中计算出来的。很明显,程序清单中的程序并不是十分
104 *   有效的。笔者只是用这种方法告诉大家一个公式,这样用户就可以知道怎样计算总的节拍数了。真正有意义的只
105 *   是OS_TICKS_PER_SEC。下段程序决定了最接近需要延迟的时间的时钟节拍总数。500/OS_TICKS_PER_SECOND的值
106 *   基本上与0.5个节拍对应的毫秒数相同。例如,若将时钟频率(OS_TICKS_PER_SEC)设置成100Hz(10ms),4ms的延时
107 *   不会产生任何延时!而5ms的延时就等于延时10ms。
108 */
109     //计算程序输入的总的节拍数
110         ticks = ((INT32U)hours * 3600L + (INT32U)minutes * 60L + (INT32U)seconds) * OS_TICKS_PER_SEC
111               + OS_TICKS_PER_SEC * ((INT32U)milli + 500L / OS_TICKS_PER_SEC) / 1000L;
112 /*
113 *   uC/OS-ii支持的延时最长为65,535个节拍。要想支持更长时间的延时,OSTimeDlyHMSM()确定了用户想延时多少
114 *   次超过65,535个节拍的数目和剩下的节拍数。例如,若OS_TICKS_PER_SEC的值为100,用户想延时15分钟,则
115 *   OSTimeDlyHMSM()会延时15x60x100=90,000个时钟。这个延时会被分割成两次32,768个节拍的延时(因为用户只能
116 *   延时65,535个节拍而不是65536个节拍)和一次24,464个节拍的延时。在这种情况下,OSTimeDlyHMSM()首先考虑
117 *   剩下的节拍,然后是超过65,535的节拍数(即两个32,768个节拍延时)。
118 */
119         loops = (INT16U)(ticks / 65536L);     //计算得商得倍数(多少个65536 时钟节拍)
120         ticks = ticks % 65536L;   //计算得余数
121         OSTimeDly((INT16U)ticks); //先作余数清除
122         while (loops > 0) {       //如果节拍数超过65536 个时钟节拍
123             OSTimeDly(32768);     //执行两次延时,实现共65536 个时钟节拍
124             OSTimeDly(32768);
125             loops--;              //继续减1,直到为0
126         }
127         return (OS_NO_ERR);       //返回(函数调用成功)
128     }
129     return (OS_TIME_ZERO_DLY);    //返回(四个参数全为0)
130 }
131 #endif
132 /*$PAGE*/
133 /*
134 *********************************************************************************************************
135 *             唤醒一个用OSTimeDly()或OSTimeDlyHMSM()函数延时的任务(RESUME A DELAYED TASK)
136 *
137 * 描述: 唤醒一个用OSTimeDly()或OSTimeDlyHMSM()函数延时的任务
138 *       OSTimeDlyResume()函数不能唤醒一个用OSTimeDlyHMSM()延时,且延时时间总计超过65535个时钟节拍的
139 *       任务。例如,如果系统时钟为100Hz,OSTimeDlyResume()不能唤醒延时OSTimeDlyHMSM(0,10,55,350)
140 *       或更长时间的任务。
141 *   (OSTimeDlyHMSM(0,10,55,350)共延时[10 minutes * 60 + (55+0.35)seconds ] * 100 = 65,535次时
142 *       钟节拍---译者注)
143 *
144 * 参数: prio   为指定要唤醒任务的优先级
145 *
146 * 返回: OS_NO_ERR          函数调用成功
147 *       OS_PRIO_INVALID    参数指定的优先级大于OS_LOWEST_PRIO
148 *       OS_TIME_NOT_DLY    要唤醒的任务不在延时状态
149 *       OS_TASK_NOT_EXIST  指定的任务不存在
150 *
151 * 注意:用户不应该用OSTimeDlyResume()去唤醒一个设置了等待超时操作,并且正在等待事件发生的任务。操作的
152 *       结果是使该任务结束等待,除非的确希望这么做。
153 *********************************************************************************************************
154 *       uC/OS-ii允许用户结束延时正处于延时期的任务。延时的任务可以不等待延时期满,而是通过其它任务取
155 *       消延时来使自己处于就绪态。这可以通过调用OSTimeDlyResume()和指定要恢复的任务的优先级来完常慰
156 *       实际上,OSTimeDlyResume()也可以唤醒正在等待事件(参看任务间的通讯和同步)的任务,虽然这一点并
157 *       没有提到过。在这种情况下,等待事件发生的任务会考虑是否终止等待事件。
158 *   OSTimeDlyResume()的代码如程序,它首先要确保指定的任务优先级有效。接着,OSTimeDlyResume()要确
159 *       认要结束延时的任务是确实存在的。如果任务存在,OSTimeDlyResume()会检验任务是否在等待延时期满。
160 *       只要OS_TCB域中的OSTCBDly包含非0值就表明任务正在等待延时期满,因为任务调用了OSTimeDly(),
161 *       OSTimeDlyHMSM()或其它在第六章中所描述的PEND函数。然后延时就可以通过强制命令OSTCBDly为0来取消
162 *       。延时的任务有可能已被挂起了,这样的话,任务只有在没有被挂起的情况下才能处于就绪状态。当上面
163 *       的条件都满足后,任务就会被放在就绪表中。这时,OSTimeDlyResume()会调用任务调度程序来看被恢复
164 *       的任务是否拥有比当前任务更高的优先级。这会导致任务的切换。
165 *********************************************************************************************************
166 */
167
168 #if OS_TIME_DLY_RESUME_EN > 0              //允许生成OSTimeDlyResume() 函数代码
169 INT8U  OSTimeDlyResume (INT8U prio)        //唤醒一个用OSTimeDly()或OSTimeDlyHMSM()函数的任务(优先级)
170 {
171 #if OS_CRITICAL_METHOD == 3                //中断函数被设定为模式3
172     OS_CPU_SR  cpu_sr;
173 #endif
174     OS_TCB    *ptcb;                       //定义任务控制块优先级表变量
175
176
177     if (prio >= OS_LOWEST_PRIO) {          //当任务指针大于等于最低(大)优先级时,确保优先级有效
178         return (OS_PRIO_INVALID);          //返回(参数指定的优先级大于OS_LOWEST_PRIO)
179     }
180     OS_ENTER_CRITICAL();                   //关闭中断
181     ptcb = (OS_TCB *)OSTCBPrioTbl[prio];   //ptcb = 任务控制块优先级表当前优先级
182     if (ptcb != (OS_TCB *)0) {             //确保要结束的延时的任务是确实存在的
183         if (ptcb->OSTCBDly != 0) {         //如果任务存在,程序会检验任务是否在等待延时期满,只要任务
184                                            //控制块的.OSTCBDly域非0值,就表明任务正在等待延时期满,因
185                                            //为任务调用了OSTimeDly()、OSTimeDlyHMSM()或其它的pend函数
186             ptcb->OSTCBDly  = 0;           //通过使 .OSTCBDly为0而取消延时
187             if ((ptcb->OSTCBStat & OS_STAT_SUSPEND) == 0x00) {
188                                            //延时的任务有可能已被挂起,然而任务在没有被挂起的情况下,
189                                            //才能处于就绪态
190                 OSRdyGrp               |= ptcb->OSTCBBitY;
191                 OSRdyTbl[ptcb->OSTCBY] |= ptcb->OSTCBBitX;
192                                            //当上面的条件都满足时,任务就会被放在就绪表中
193                 OS_EXIT_CRITICAL();        //打开中断
194                 OS_Sched();                //任务调度程序会执行下一个优先级最高的就绪任务(任务调度)
195             } else {                       //不然
196                 OS_EXIT_CRITICAL();        //打开中断
197             }
198             return (OS_NO_ERR);            //函数调用成功
199         } else {                           //否则
200             OS_EXIT_CRITICAL();            //打开中断
201             return (OS_TIME_NOT_DLY);      //返回(要唤醒的任务不在延时状态)
202         }
203     }
204     OS_EXIT_CRITICAL();                    //打开中断
205     return (OS_TASK_NOT_EXIST);            //返回(指定的任务不存在)
206 }
207 #endif
208 /*$PAGE*/
209 /*
210 *********************************************************************************************************
211 *                         获取当前系统时钟数值(GET CURRENT SYSTEM TIME)
212 *
213 * 描述: 获取当前系统时钟数值。系统时钟是一个32位的计数器,记录系统上电后或时钟重新设置后的时钟计数。
214 *
215 * 附加:无论时钟节拍何时发生,uC/OS-ii都会将一个32位的计数器加1。这个计数器在用户调用OSStart()初始
216 *       化多任务和4,294,967,295个节拍执行完一遍的时候从0开始计数。在时钟节拍的频率等于100Hz的时候,
217 *       这个32位的计数器每隔497天就重新开始计数。用户可以通过调用OSTimeGet()来获得该计数器的当前值。
218 *       也可以通过调用OSTimeSet()来改变该计数器的值。OSTimeGet()和OSTimeSet()两个函数的代码如程序。
219 *       注意,在访问OSTime的时候中断是关掉的。这是因为在大多数8位处理器上增加和拷贝一个32位的数都需
220 *       要数条指令,这些指令一般都需要一次执行完毕,而不能被中断等因素打断
221 *
222 * 参数: 无
223 *
224 * 返回: 当前时钟计数(时钟节拍数)
225 *********************************************************************************************************
226 */
227
228 #if OS_TIME_GET_SET_EN > 0         //允许生成OSTimeGet() 函数代码
229 INT32U  OSTimeGet (void)           //获取当前系统时钟数值
230 {
231 #if OS_CRITICAL_METHOD == 3        //中断函数被设定为模式3
232     OS_CPU_SR  cpu_sr;
233 #endif
234     INT32U     ticks;              //定义节拍数
235
236
237     OS_ENTER_CRITICAL();           //关闭中断
238     ticks = OSTime;                //获取当前系统时钟数值
239     OS_EXIT_CRITICAL();            //打开中断
240     return (ticks);                //返回系统时钟数值
241 }
242 #endif
243
244 /*
245 *********************************************************************************************************
246 *                                 设置当前系统时钟数值(SET SYSTEM CLOCK)
247 *
248 * 描述: 设置当前系统时钟数值。系统时钟是一个32位的计数器, 记录系统上电后或时钟重新设置后的时钟计数.
249 *
250 * 参数: ticks  要设置的时钟数,单位是时钟节拍数.
251 *
252 * 返回: 无
253 *********************************************************************************************************
254 */
255
256 #if OS_TIME_GET_SET_EN > 0         //允许生成OSTimeSet() 函数代码
257 void  OSTimeSet (INT32U ticks)     //设置当前系统时钟数值
258 {
259 #if OS_CRITICAL_METHOD == 3        //中断函数被设定为模式3
260     OS_CPU_SR  cpu_sr;
261 #endif
262
263
264     OS_ENTER_CRITICAL();           //关闭中断
265     OSTime = ticks;                //设置当前系统时钟数值为多少个节拍数
266     OS_EXIT_CRITICAL();            //打开中断
267 }
268 #endif
269

目录
相关文章
|
17天前
|
存储 编解码 iOS开发
Python模块操作:time—Clock Time(一)
Python模块操作:time—Clock Time(一)
16 0
|
17天前
|
存储 iOS开发 MacOS
Python模块操作:time—Clock Time(二)
Python模块操作:time—Clock Time(二)
28 0
|
10月前
|
Go
go time.After() time.Ticker
go time.After() time.Ticker
33 0
|
11月前
Time
Time
151 0
函数 os.time
函数 os.time
177 0
函数 os.date
函数 os.date
178 0
|
Unix
TIME
1171 0