source: soft/giet_vm/giet_drivers/tim_driver.c @ 323

Last change on this file since 323 was 320, checked in by alain, 10 years ago

All drivers have been modified to use only the information
contained in the hard_config.h file

File size: 9.1 KB
Line 
1//////////////////////////////////////////////////////////////////////////////////////
2// File     : timer_driver.c
3// Date     : 23/05/2013
4// Author   : alain greiner
5// Copyright (c) UPMC-LIP6
6//////////////////////////////////////////////////////////////////////////////////////
7// The timer_driver.c and timer_driver.h files are part ot the GIET-VM nano-kernel.
8// This driver supports the SoCLib vci_multi_timer component.
9//
10// It can exist several multi_timers in the architecture (at most one per cluster),
11// and each one can contain several timers (called channels).
12//
13// There is two types of timers:
14// - "system" timers : one per processor, used for context switch.
15//   local_id in [0, NB_PROCS_MAX-1],
16// - "user" timers : requested by the task in the mapping_info data structure.
17//   For each user timer, the timer_id is stored in the context of the task.
18// The global index is cluster_xy * (NB_PROCS_MAX + NB_TIM_CHANNELS) + local_id
19//
20// The NB_PROCS_MAX and NB_TIM_CHANNELS values must be defined in hard_config.h file.
21//
22// The virtual base address of the segment associated to a channel is:
23//     SEG_TIM_BASE + cluster_xy * VSEG_CLUSTER_INCREMENT + TIMER_SPAN * timer_id
24//
25// The SEG_TIM_BASE and VSEG_CLUSTER_INCREMENT must be defined in hard_config.h.
26/////////////////////////////////////////////////////////////////////////////////////
27
28#include <giet_config.h>
29#include <tim_driver.h>
30#include <xcu_driver.h>
31#include <tty_driver.h>
32#include <utils.h>
33
34#if !defined(SEG_TIM_BASE)
35# error: You must define SEG_TIM_BASE in the hard_config.h file
36#endif
37
38#if !defined(VSEG_CLUSTER_INCREMENT)
39# error: You must define VSEG_CLUSTER_INCREMENT in the hard_config.h file
40#endif
41
42#if !defined(X_SIZE)
43# error: You must define X_SIZE in the hard_config.h file
44#endif
45
46#if !defined(Y_SIZE)
47# error: You must define X_SIZE in the hard_config.h file
48#endif
49
50#if !defined(X_WIDTH)
51# error: You must define X_WIDTH in the hard_config.h file
52#endif
53
54#if !defined(Y_WIDTH)
55# error: You must define X_WIDTH in the hard_config.h file
56#endif
57
58#if !defined(NB_PROCS_MAX)
59# error: You must define NB_PROCS_MAX in the hard_config.h file
60#endif
61
62#if !defined(NB_TIM_CHANNELS)
63#define NB_TIM_CHANNELS 0
64#endif
65
66#if ( (NB_TIM_CHANNELS + NB_PROC_MAX) > 32 )
67# error: NB_TIM_CHANNELS + NB_PROCS_MAX cannot be larger than 32
68#endif
69
70///////////////////  Timer global variables ////////////////////////////////////////
71
72#define in_unckdata __attribute__((section (".unckdata")))
73
74#if (NB_TIM_CHANNELS > 0)
75in_unckdata volatile unsigned char _user_timer_event[(1<<X_WIDTH)*(1<<Y_WIDTH)*NB_TIM_CHANNELS] 
76                        = { [0 ... (((1<<X_WIDTH)*(1<<Y_WIDTH)*NB_TIM_CHANNELS) - 1)] = 0 };
77#endif
78
79////////////////////////////////////////////////////////////////////////////////////
80// This function activates a timer in the vci_timer component
81// by writing in the proper register the period value.
82// It can be used by both the kernel to initialise a "system" timer,
83// or by a task (through a system call) to configure an "user" timer.
84///////////////////////////////////////////////////////////////////////////////////
85void _timer_start( unsigned int cluster_xy, 
86                   unsigned int local_id, 
87                   unsigned int period) 
88{
89#if NB_TIM_CHANNELS
90
91    // parameters checking
92    unsigned int x = cluster_xy >> Y_WIDTH;
93    unsigned int y = cluster_xy & ((1<<Y_WIDTH)-1);
94    if ( (x >= X_SIZE) || (y >= Y_SIZE) || (local_id >= NB_TIM_CHANNELS) )
95    {
96        _printf("[GIET ERROR] in _timer_start()\n");
97        _exit();
98    }
99
100    unsigned int* timer_address = (unsigned int *) ( SEG_TIM_BASE +
101                                  (cluster_xy * VSEG_CLUSTER_INCREMENT) );
102
103    timer_address[local_id * TIMER_SPAN + TIMER_PERIOD] = period;
104    timer_address[local_id * TIMER_SPAN + TIMER_MODE] = 0x3;
105
106#else
107    _printf("[GIET ERROR] _timer_start() should not be called when NB_TIM_CHANNELS is 0\n");
108    _exit();
109#endif
110}
111
112//////////////////////////////////////////////////////////////////////////////
113// This function desactivates a timer in the vci_timer component
114// by writing in the proper register.
115// Returns 0 if success, > 0 if error.
116//////////////////////////////////////////////////////////////////////////////
117void _timer_stop( unsigned int cluster_xy, 
118                  unsigned int local_id) 
119{
120#if NB_TIM_CHANNELS
121
122    // parameters checking
123    unsigned int x = cluster_xy >> Y_WIDTH;
124    unsigned int y = cluster_xy & ((1<<Y_WIDTH)-1);
125    if ( (x >= X_SIZE) || (y >= Y_SIZE) || (local_id >= NB_TIM_CHANNELS) )
126    {
127        _printf("[GIET ERROR] in _timer_stop()\n");
128        _exit();
129    }
130
131    unsigned int* timer_address = (unsigned int *) ( SEG_TIM_BASE +
132                                  (cluster_xy * VSEG_CLUSTER_INCREMENT) );
133
134    timer_address[local_id * TIMER_SPAN + TIMER_MODE] = 0;
135
136#else
137    _printf("[GIET ERROR] _timer_stop() should not be called when NB_TIM_CHANNELS is 0\n");
138    _exit();
139#endif
140}
141
142//////////////////////////////////////////////////////////////////////////////
143// This function acknowlegge a timer interrupt in the vci_timer 
144// component by writing in the proper register.
145// It can be used by both the isr_switch() for a "system" timer,
146// or by the _isr_timer() for an "user" timer.
147// Returns 0 if success, > 0 if error.
148//////////////////////////////////////////////////////////////////////////////
149void _timer_reset_irq( unsigned int cluster_xy, 
150                       unsigned int local_id ) 
151{
152#if NB_TIM_CHANNELS
153
154    // parameters checking
155    unsigned int x = cluster_xy >> Y_WIDTH;
156    unsigned int y = cluster_xy & ((1<<Y_WIDTH)-1);
157    if ( (x >= X_SIZE) || (y >= Y_SIZE) || (local_id >= NB_TIM_CHANNELS) )
158    {
159        _printf("[GIET ERROR] in _timer_reset_irq()\n");
160        _exit();
161    }
162
163    unsigned int* timer_address = (unsigned int *) ( SEG_TIM_BASE +
164                                  (cluster_xy * VSEG_CLUSTER_INCREMENT) );
165
166    timer_address[local_id * TIMER_SPAN + TIMER_RESETIRQ] = 0;
167
168#else
169    _printf("[GIET ERROR] _timer_reset_irq() should not be called when NB_TIM_CHANNELS is 0\n");
170    _exit();
171#endif
172}
173
174/////////////////////////////////////////////////////////////////////////////
175// This function resets the timer counter. To do so, we re-write the period
176// in the proper register, what causes the count to restart.
177// The period value is read from the same (TIMER_PERIOD) register,
178// this is why in appearance we do nothing useful (read a value
179// from a register and write this value in the same register)
180// This function is called during a context switch (user or preemptive)
181//////////////////////////////////////////////////////////////////////i//////
182void _timer_reset_cpt( unsigned int cluster_xy, 
183                       unsigned int local_id) 
184{
185#if NB_TIM_CHANNELS
186
187    // parameters checking
188    unsigned int x = cluster_xy >> Y_WIDTH;
189    unsigned int y = cluster_xy & ((1<<Y_WIDTH)-1);
190    if ( (x >= X_SIZE) || (y >= Y_SIZE) || (local_id >= NB_TIM_CHANNELS) )
191    {
192        _printf("[GIET ERROR in _timer_reset_cpt()\n");
193        _exit();
194    }
195
196    // We suppose that the TIMER_MODE register value is 0x3
197    unsigned int* timer_address = (unsigned int *) ( SEG_TIM_BASE +
198                                  (cluster_xy * VSEG_CLUSTER_INCREMENT) );
199
200    unsigned int period = timer_address[local_id * TIMER_SPAN + TIMER_PERIOD];
201    timer_address[local_id * TIMER_SPAN + TIMER_PERIOD] = period;
202
203#else
204    _printf("[GIET ERROR] _timer_reset_cpt should not be called when NB_TIM_CHANNELS is 0\n");
205    _exit();
206#endif
207}
208
209///////////////////////////////////////////////////////////////////////////////////
210// This ISR handles the IRQs generated by the "user" timers that are
211// replicated in all clusters.
212// The IRQs generated by the "system" timers should be handled by _isr_switch().
213// It can be a HWI or a PTI.
214// The channel argument is the user timer local index.
215//     timer_global_id = cluster_id*(NB_TIM_CHANNELS) + channel
216// The ISR acknowledges the IRQ and registers the event in the proper entry
217// of the _user_timer_event[] array, and a log message is displayed on TTY0.
218///////////////////////////////////////////////////////////////////////////////////
219void _timer_isr( unsigned int irq_type,   // HWI / PTI
220                 unsigned int irq_id,     // index returned by XCU
221                 unsigned int channel )   // user timer index
222{
223#if NB_TIM_CHANNELS
224
225    unsigned int cluster_xy = _get_procid() / NB_PROCS_MAX;
226
227    // acknowledge IRQ depending on type
228    if   ( irq_type == IRQ_TYPE_HWI )  _timer_reset_irq( cluster_xy, channel );
229    else                               _xcu_timer_reset_irq( cluster_xy, irq_id );
230
231    // register the event
232    _user_timer_event[cluster_xy * NB_TIM_CHANNELS + channel] = 1;
233
234    // display a message on TTY 0
235    _printf("\n[GIET WARNING] User Timer IRQ at cycle %d / cluster = %x / channel = %d\n",
236            _get_proctime(), cluster_xy, channel );
237
238#else
239    _printf("[GIET ERROR] _timer_isr() should not be called when NB_TIM_CHANNELS == 0\n");
240    _exit();
241#endif
242}
243
244
245
246// Local Variables:
247// tab-width: 4
248// c-basic-offset: 4
249// c-file-offsets:((innamespace . 0)(inline-open . 0))
250// indent-tabs-mode: nil
251// End:
252// vim: filetype=c:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
253
Note: See TracBrowser for help on using the repository browser.