1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14:
15:
16: 17: 18: 19:
20:
21: #include "kernel.h"
22: #include "timer.h"
23: #include "task.h"
24: #include "tkdev_timer.h"
25: #include <sys/rominfo.h>
26:
27: 28: 29:
30: EXPORT RELTIM_U TIMER_PERIOD;
31:
32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42:
43: EXPORT LSYSTIM current_time;
44: EXPORT LSYSTIM real_time_ofs;
45:
46: 47: 48:
49: LOCAL QUEUE timer_queue;
50:
51: 52: 53:
54: EXPORT ER timer_initialize( void )
55: {
56: INT n, t[2];
57:
58:
59: n = _tk_get_cfn(SCTAG_TTIMPERIOD, t, 2);
60: if ( n < 1 ) return E_SYS;
61: if ( n < 2 ) t[1] = 0;
62: TIMER_PERIOD = to_usec(t[0]) + t[1];
63: if ( TIMER_PERIOD < MIN_TIMER_PERIOD
64: || TIMER_PERIOD > MAX_TIMER_PERIOD ) {
65: return E_SYS;
66: }
67:
68: current_time = real_time_ofs = ltoll(0);
69: QueInit(&timer_queue);
70:
71:
72: start_hw_timer();
73:
74: return E_OK;
75: }
76:
77: 78: 79:
80: EXPORT void timer_shutdown( void )
81: {
82: terminate_hw_timer();
83: }
84:
85: 86: 87: 88: 89: 90:
91: EXPORT RELTIM_U adjust_time( void )
92: {
93: return get_hw_timer_usec();
94: }
95:
96: 97: 98:
99: LOCAL void enqueue_tmeb( TMEB *event )
100: {
101: QUEUE *q;
102:
103: for ( q = timer_queue.next; q != &timer_queue; q = q->next ) {
104: if ( ll_cmp(event->time, ((TMEB*)q)->time) < 0) {
105: break;
106: }
107: }
108: QueInsert(&event->queue, q);
109: }
110:
111: 112: 113: 114: 115: 116: 117: 118: 119: 120: 121: 122: 123: 124:
125: EXPORT void timer_insert( TMEB *event, TMO_U tmout, CBACK callback, void *arg )
126: {
127: event->callback = callback;
128: event->arg = arg;
129:
130: if ( tmout == TMO_FEVR ) {
131: QueInit(&event->queue);
132: } else {
133: 134:
135: event->time = ll_add( ll_add(current_time, ltoll(tmout)),
136: uitoll(adjust_time()) );
137: enqueue_tmeb(event);
138: }
139: }
140:
141: EXPORT void timer_insert_reltim( TMEB *event, RELTIM_U tmout, CBACK callback, void *arg )
142: {
143: event->callback = callback;
144: event->arg = arg;
145:
146: 147:
148: event->time = ll_add( ll_add(current_time, ultoll(tmout)),
149: uitoll(adjust_time()) );
150: enqueue_tmeb(event);
151: }
152:
153: 154: 155: 156: 157: 158:
159: EXPORT void timer_insert_abs( TMEB *evt, LSYSTIM time, CBACK cback, void *arg )
160: {
161: evt->callback = cback;
162: evt->arg = arg;
163: evt->time = time;
164: enqueue_tmeb(evt);
165: }
166:
167:
168:
169: 170: 171: 172: 173: 174:
175: EXPORT void timer_handler( void )
176: {
177: TMEB *event;
178:
179: clear_hw_timer_interrupt();
180:
181: BEGIN_CRITICAL_SECTION;
182: current_time = ll_add(current_time, uitoll(TIMER_PERIOD));
183:
184: if ( ctxtsk != NULL ) {
185:
186: if ( ctxtsk->sysmode > 0 ) {
187: ctxtsk->stime += TIMER_PERIOD;
188: } else {
189: ctxtsk->utime += TIMER_PERIOD;
190: }
191:
192: if ( schedtsk == ctxtsk ) {
193: schedtsk = time_slice_schedule(ctxtsk);
194: if ( schedtsk != ctxtsk ) {
195: dispatch_request();
196: }
197: }
198: }
199:
200:
201: while ( !isQueEmpty(&timer_queue) ) {
202: event = (TMEB*)timer_queue.next;
203: if ( ll_cmp(event->time, current_time) > 0 ) {
204: break;
205: }
206:
207: QueRemove(&event->queue);
208: if ( event->callback != NULL ) {
209: (*event->callback)(event->arg);
210: }
211: }
212:
213: END_CRITICAL_SECTION;
214:
215: end_of_hw_timer_interrupt();
216: }