4
Copyright 2008-2012 Michel Pollet <buserror@gmail.com>
6
This file is part of simavr.
8
simavr is free software: you can redistribute it and/or modify
9
it under the terms of the GNU General Public License as published by
10
the Free Software Foundation, either version 3 of the License, or
11
(at your option) any later version.
13
simavr is distributed in the hope that it will be useful,
14
but WITHOUT ANY WARRANTY; without even the implied warranty of
15
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
GNU General Public License for more details.
18
You should have received a copy of the GNU General Public License
19
along with simavr. If not, see <http://www.gnu.org/licenses/>.
27
#include "sim_cycle_timers.h"
29
#define QUEUE(__q, __e) { \
30
(__e)->next =( __q); \
33
#define DETACH(__q, __l, __e) { \
35
(__l)->next =( __e)->next; \
37
(__q) =( __e)->next; \
39
#define INSERT(__q, __l, __e) { \
41
(__e)->next =( __l)->next; \
42
(__l)->next =( __e); \
44
(__e)->next =( __q); \
49
#define DEFAULT_SLEEP_CYCLES 1000
51
void avr_cycle_timer_reset( struct avr_t * avr )
53
avr_cycle_timer_pool_t * pool = &avr->cycle_timers;
54
memset( pool, 0, sizeof(*pool) );
56
for( int i = 0; i < MAX_CYCLE_TIMERS; i++ ) // queue all slots into the free queue
58
avr_cycle_timer_slot_p t = &pool->t_slots[i];
59
QUEUE( pool->slot_free, t );
61
////avr->run_cycle_count = 1;
62
////avr->run_cycle_limit = 1;
66
/*static avr_cycle_count_t
67
avr_cycle_timer_return_sleep_run_cycles_limited(
69
avr_cycle_count_t sleep_cycle_count)
71
// run_cycle_count is bound to run_cycle_limit but NOT less than 1 cycle...
72
// this is not an error!.. unless you like deadlock.
73
avr_cycle_count_t run_cycle_count =( (avr->run_cycle_limit >= sleep_cycle_count) ?
74
sleep_cycle_count : avr->run_cycle_limit);
76
avr->run_cycle_count = run_cycle_count ? run_cycle_count : 1;
78
// sleep cycles are returned unbounded thus preserving original behavior.
79
return(sleep_cycle_count);
82
/*static void avr_cycle_timer_reset_sleep_run_cycles_limited( avr_t *avr )
84
avr_cycle_timer_pool_t * pool = &avr->cycle_timers;
85
avr_cycle_count_t sleep_cycle_count = DEFAULT_SLEEP_CYCLES;
89
if( pool->timer->when > avr->cycle ) sleep_cycle_count = pool->timer->when - avr->cycle;
90
else sleep_cycle_count = 0;
92
////avr_cycle_timer_return_sleep_run_cycles_limited( avr, sleep_cycle_count );
95
// no sanity checks checking here, on purpose
96
static void avr_cycle_timer_insert(
98
avr_cycle_count_t when,
99
avr_cycle_timer_t event,
102
avr_cycle_timer_pool_t * pool = &avr->cycle_timers;
106
avr_cycle_timer_slot_p slot = pool->slot_free;
109
AVR_LOG(avr, LOG_ERROR, "CYCLE: %s: ran out of timers( %d)!\n", __func__, MAX_CYCLE_TIMERS);
113
pool->slot_free = slot->next;
119
// find its place in the list
120
avr_cycle_timer_slot_p loop = pool->t_slot, last = NULL;
123
if( loop->when > when ) break;
128
INSERT( pool->t_slot, last, slot );
131
void avr_cycle_timer_register( avr_t * avr, avr_cycle_count_t when, avr_cycle_timer_t timer, void* param)
133
avr_cycle_timer_pool_t * pool = &avr->cycle_timers;
135
avr_cycle_timer_cancel( avr, timer, param ); // remove it if it was already scheduled
137
if( !pool->slot_free )
139
AVR_LOG(avr, LOG_ERROR, "CYCLE: %s: pool is full( %d)!\n", __func__, MAX_CYCLE_TIMERS);
142
avr_cycle_timer_insert( avr, when, timer, param );
143
////avr_cycle_timer_reset_sleep_run_cycles_limited(avr);
146
void avr_cycle_timer_register_usec( avr_t* avr, uint32_t when, avr_cycle_timer_t timer, void* param)
148
avr_cycle_timer_register( avr, avr_usec_to_cycles(avr, when), timer, param);
151
void avr_cycle_timer_cancel( avr_t* avr, avr_cycle_timer_t event, void* param)
153
avr_cycle_timer_pool_t * pool = &avr->cycle_timers;
155
// find its place in the list
156
avr_cycle_timer_slot_p t = pool->t_slot, last = NULL;
159
if( t->event == event && t->param == param)
161
DETACH(pool->t_slot, last, t);
162
QUEUE(pool->slot_free, t);
168
////avr_cycle_timer_reset_sleep_run_cycles_limited(avr);
172
* Check to see if a timer is present, if so, return the number( +1) of
173
* cycles left for it to fire, and if not present, return zero
176
avr_cycle_timer_status(
178
avr_cycle_timer_t event,
181
avr_cycle_timer_pool_t * pool = &avr->cycle_timers;
183
// find its place in the list
184
avr_cycle_timer_slot_p t = pool->t_slot;
187
if( t->event == event && t->param == param)
189
return 1 +( t->when - avr->cycle);
197
* run through all the timers, call the ones that needs it,
198
* clear the ones that wants it, and calculate the next
199
* potential cycle we could sleep for...
201
avr_cycle_count_t avr_cycle_timer_process( avr_t* avr )
203
avr_cycle_timer_pool_t* pool = &avr->cycle_timers;
208
avr_cycle_timer_slot_p slot = pool->t_slot;
209
avr_cycle_count_t when = slot->when;
211
if( when > avr->cycle)
212
return 0; ////avr_cycle_timer_return_sleep_run_cycles_limited( avr, when-avr->cycle);
214
// detach from active timers
215
pool->t_slot = slot->next;
219
avr_cycle_count_t w = slot->event( avr, when, slot->param );
220
// make sure the return value is either zero, or greater
221
// than the last one to prevent infinite loop here
222
when = w > when ? w : 0;
223
} while( when && when <= avr->cycle );
225
if( when ) // reschedule then
226
avr_cycle_timer_insert( avr, when-avr->cycle, slot->event, slot->param );
228
QUEUE( pool->slot_free, slot ); // requeue this one into the free ones
230
while( pool->t_slot);
232
// original behavior was to return 1000 cycles when no timers were present...
233
// run_cycles are bound to at least one cycle but no more than requested limit...
234
// value passed here is returned unbounded, thus preserving original behavior.
235
return 0;///avr_cycle_timer_return_sleep_run_cycles_limited(avr, DEFAULT_SLEEP_CYCLES);